| 666 | } |
| 667 | |
| 668 | func (c *Client) checkRateLimit(response *http.Response) error { |
| 669 | if response == nil { |
| 670 | return nil |
| 671 | } |
| 672 | remainingValue := strings.TrimSpace(response.Header.Get("X-RateLimit-Remaining")) |
| 673 | if remainingValue == "" { |
| 674 | return nil |
| 675 | } |
| 676 | remaining, err := strconv.Atoi(remainingValue) |
| 677 | if err != nil { |
| 678 | if c.logger != nil { |
| 679 | c.logger.Debug( |
| 680 | "github: invalid X-RateLimit-Remaining header", |
| 681 | "value", |
| 682 | remainingValue, |
| 683 | "error", |
| 684 | err, |
| 685 | "url", |
| 686 | requestURLString(response), |
| 687 | ) |
| 688 | } |
| 689 | return nil |
| 690 | } |
| 691 | if remaining == 0 { |
| 692 | if response.StatusCode == http.StatusForbidden || response.StatusCode == http.StatusTooManyRequests { |
| 693 | rateLimitErr := errors.New("github: rate limit exceeded; set GITHUB_TOKEN for higher limits") |
| 694 | return joinErrors( |
| 695 | rateLimitErr, |
| 696 | closeResponseBody(response.Body, fmt.Sprintf("rate limit response for %s", requestURLString(response))), |
| 697 | ) |
| 698 | } |
| 699 | if c.logger != nil { |
| 700 | c.logger.Warn( |
| 701 | "github: rate limit exhausted after successful response", |
| 702 | "status", response.StatusCode, |
| 703 | "url", requestURLString(response), |
| 704 | ) |
| 705 | } |
| 706 | } |
| 707 | if remaining < rateLimitWarnThreshold && c.logger != nil { |
| 708 | c.logger.Warn("github: rate limit running low", "remaining", remaining, "url", requestURLString(response)) |
| 709 | } |
| 710 | return nil |
| 711 | } |
| 712 | |
| 713 | func parseRepoSlug(slug string) (repoSlug, error) { |
| 714 | trimmed := strings.TrimSpace(slug) |