Пример #1
0
        public void TestIsRateLimit(bool expected, string remainin)
        {
            var headers = new HttpTestHeaders
            {
                { "X-RateLimit-Remainin", remainin },
            };

            var github = new Github(io.Object, config.Object, null, transport.Object);

            Assert.AreEqual(expected, github.IsRateLimit(headers));
        }
Пример #2
0
        /// <inheritdoc cref="GetRemoteContent(string, bool)"/>
        /// <param name="fetchingRepoData">Whether is fetching the main repository data.</param>
        protected (string Content, HttpHeaders Headers) GetRemoteContent(string uri, bool fetchingRepoData = false)
        {
            try
            {
                return(base.GetRemoteContent(uri));
            }
            catch (TransportException ex)
            {
                var github = new Github(IO, Config, Process, GetTransport());
                switch (ex.HttpStatusCode)
                {
                case HttpStatusCode.Unauthorized:
                case HttpStatusCode.NotFound:
                    if (!fetchingRepoData)
                    {
                        throw;
                    }

                    if (github.AuthorizeOAuth(host))
                    {
                        return(base.GetRemoteContent(uri));
                    }

                    if (!IO.IsInteractive && AttemptCloneFallback())
                    {
                        return(null, null);
                    }

                    var scopesIssued = Array.Empty <string>();
                    var scopesNeeded = Array.Empty <string>();
                    var headers      = ex.GetHeaders();
                    if (headers != null)
                    {
                        if (headers.TryGetValues("X-OAuth-Scopes", out IEnumerable <string> values))
                        {
                            var scopes = string.Join(string.Empty, values);
                            scopesIssued = scopes.Split(' ');
                        }

                        if (headers.TryGetValues("X-Accepted-OAuth-Scopes", out values))
                        {
                            var scopes = string.Join(string.Empty, values);
                            scopesNeeded = scopes.Split(' ');
                        }
                    }

                    var scopesFailed = Arr.Difference(scopesIssued, scopesNeeded);

                    // non-authenticated requests get no scopesNeeded, so ask
                    // for credentials authenticated requests which failed some
                    // scopes should ask for new credentials too
                    if (headers == null || scopesNeeded.Length == 0 || scopesFailed.Length > 0)
                    {
                        github.AuthorizeOAuthInteractively(host, $"Your GitHub credentials are required to fetch private repository metadata (<info>{uri}</info>)");
                    }

                    return(base.GetRemoteContent(uri));

                case HttpStatusCode.Forbidden:
                    if (!IO.HasAuthentication(host) && github.AuthorizeOAuth(host))
                    {
                        return(base.GetRemoteContent(uri));
                    }

                    if (!IO.IsInteractive && fetchingRepoData && AttemptCloneFallback())
                    {
                        return(null, null);
                    }

                    var isRateLimited = github.IsRateLimit(ex.GetHeaders());
                    if (!IO.HasAuthentication(host))
                    {
                        if (!IO.IsInteractive)
                        {
                            IO.WriteError($"<error>GitHub API limit exhausted. Failed to get metadata for the {uri} repository, try running in interactive mode so that you can enter your GitHub credentials to increase the API limit</error>");
                            throw;
                        }

                        github.AuthorizeOAuthInteractively(host, $"API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>{uri}</info>)");
                        return(base.GetRemoteContent(uri));
                    }

                    if (isRateLimited)
                    {
                        var(limit, reset) = github.GetRateLimit(ex.GetHeaders());
                        IO.WriteError($"<error>GitHub API limit ({limit} calls/hr) is exhausted. You are already authorized so you have to wait until {reset} before doing more requests</error>");
                    }

                    throw;

                default:
                    throw;
                }
            }
        }