Browse Source

Deal with 202 Accepted Status Code

Fixes #486.
Closes #488.

Change-Id: I31ff003552dbffaca78c740b89d54150b81c525c
Carlos Alexandro Becker 9 years ago
committed by Glenn Lewis
parent
commit
231da324fa
5 changed files with 77 additions and 11 deletions
  1. +17
    -0
      README.md
  2. +15
    -0
      github/doc.go
  3. +19
    -2
      github/github.go
  4. +6
    -0
      github/repos_forks.go
  5. +20
    -9
      github/repos_stats.go

+ 17
- 0
README.md View File

@ -99,6 +99,23 @@ if _, ok := err.(*github.RateLimitError); ok {
Learn more about GitHub rate limiting at Learn more about GitHub rate limiting at
http://developer.github.com/v3/#rate-limiting. http://developer.github.com/v3/#rate-limiting.
### Accepted Status ###
Some endpoints may return a 202 Accepted status code, meaning that the
information required is not yet ready and was scheduled to be gathered on
the GitHub side. Methods known to behave like this are documented specifying
this behavior.
To detect this condition of error, you can check if its type is
`*github.AcceptedError`:
```go
stats, _, err := client.Repositories.ListContributorsStats(org, repo)
if _, ok := err.(*github.AcceptedError); ok {
log.Println("scheduled on GitHub side")
}
```
### Conditional Requests ### ### Conditional Requests ###
The GitHub API has good support for conditional requests which will help The GitHub API has good support for conditional requests which will help


+ 15
- 0
github/doc.go View File

@ -86,6 +86,21 @@ To detect an API rate limit error, you can check if its type is *github.RateLimi
Learn more about GitHub rate limiting at Learn more about GitHub rate limiting at
http://developer.github.com/v3/#rate-limiting. http://developer.github.com/v3/#rate-limiting.
Accepted Status
Some endpoints may return a 202 Accepted status code, meaning that the
information required is not yet ready and was scheduled to be gathered on
the GitHub side. Methods known to behave like this are documented specifying
this behavior.
To detect this condition of error, you can check if its type is
*github.AcceptedError:
stats, _, err := client.Repositories.ListContributorsStats(org, repo)
if _, ok := err.(*github.AcceptedError); ok {
log.Println("scheduled on GitHub side")
}
Conditional Requests Conditional Requests
The GitHub API has good support for conditional requests which will help The GitHub API has good support for conditional requests which will help


+ 19
- 2
github/github.go View File

@ -501,6 +501,18 @@ func (r *RateLimitError) Error() string {
r.Response.StatusCode, r.Message, r.Rate.Reset.Time.Sub(time.Now())) r.Response.StatusCode, r.Message, r.Rate.Reset.Time.Sub(time.Now()))
} }
// AcceptedError occurs when GitHub returns 202 Accepted response with an
// empty body, which means a job was scheduled on the GitHub side to process
// the information needed and cache it.
// Technically, 202 Accepted is not a real error, it's just used to
// indicate that results are not ready yet, but should be available soon.
// The request can be repeated after some time.
type AcceptedError struct{}
func (*AcceptedError) Error() string {
return "job scheduled on GitHub side; try again later"
}
// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the // AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the
// "documentation_url" field value equal to "https://developer.github.com/v3#abuse-rate-limits". // "documentation_url" field value equal to "https://developer.github.com/v3#abuse-rate-limits".
type AbuseRateLimitError struct { type AbuseRateLimitError struct {
@ -564,14 +576,19 @@ func (e *Error) Error() string {
} }
// CheckResponse checks the API response for errors, and returns them if // CheckResponse checks the API response for errors, and returns them if
// present. A response is considered an error if it has a status code outside
// the 200 range. API error responses are expected to have either no response
// present. A response is considered an error if it has a status code outside
// the 200 range or equal to 202 Accepted.
// API error responses are expected to have either no response
// body, or a JSON response body that maps to ErrorResponse. Any other // body, or a JSON response body that maps to ErrorResponse. Any other
// response body will be silently ignored. // response body will be silently ignored.
// //
// The error type will be *RateLimitError for rate limit exceeded errors, // The error type will be *RateLimitError for rate limit exceeded errors,
// *AcceptedError for 202 Accepted status codes,
// and *TwoFactorAuthError for two-factor authentication errors. // and *TwoFactorAuthError for two-factor authentication errors.
func CheckResponse(r *http.Response) error { func CheckResponse(r *http.Response) error {
if r.StatusCode == http.StatusAccepted {
return &AcceptedError{}
}
if c := r.StatusCode; 200 <= c && c <= 299 { if c := r.StatusCode; 200 <= c && c <= 299 {
return nil return nil
} }


+ 6
- 0
github/repos_forks.go View File

@ -50,6 +50,12 @@ type RepositoryCreateForkOptions struct {
// CreateFork creates a fork of the specified repository. // CreateFork creates a fork of the specified repository.
// //
// This method might return an *AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it is now computing creating the fork in a background task.
// A follow up request, after a delay of a second or so, should result
// in a successful request.
//
// GitHub API docs: https://developer.github.com/v3/repos/forks/#create-a-fork // GitHub API docs: https://developer.github.com/v3/repos/forks/#create-a-fork
func (s *RepositoriesService) CreateFork(owner, repo string, opt *RepositoryCreateForkOptions) (*Repository, *Response, error) { func (s *RepositoriesService) CreateFork(owner, repo string, opt *RepositoryCreateForkOptions) (*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) u := fmt.Sprintf("repos/%v/%v/forks", owner, repo)


+ 20
- 9
github/repos_stats.go View File

@ -39,8 +39,8 @@ func (w WeeklyStats) String() string {
// deletions and commit counts. // deletions and commit counts.
// //
// If this is the first time these statistics are requested for the given // If this is the first time these statistics are requested for the given
// repository, this method will return a non-nil error and a status code of
// 202. This is because this is the status that github returns to signify that
// repository, this method will return an *AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it is now computing the requested statistics. A follow up request, after a // it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request. // delay of a second or so, should result in a successful request.
// //
@ -78,8 +78,8 @@ func (w WeeklyCommitActivity) String() string {
// starting on Sunday. // starting on Sunday.
// //
// If this is the first time these statistics are requested for the given // If this is the first time these statistics are requested for the given
// repository, this method will return a non-nil error and a status code of
// 202. This is because this is the status that github returns to signify that
// repository, this method will return an *AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it is now computing the requested statistics. A follow up request, after a // it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request. // delay of a second or so, should result in a successful request.
// //
@ -104,6 +104,12 @@ func (s *RepositoriesService) ListCommitActivity(owner, repo string) ([]*WeeklyC
// deletions pushed to a repository. Returned WeeklyStats will contain // deletions pushed to a repository. Returned WeeklyStats will contain
// additions and deletions, but not total commits. // additions and deletions, but not total commits.
// //
// If this is the first time these statistics are requested for the given
// repository, this method will return an *AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request.
//
// GitHub API Docs: https://developer.github.com/v3/repos/statistics/#code-frequency // GitHub API Docs: https://developer.github.com/v3/repos/statistics/#code-frequency
func (s *RepositoriesService) ListCodeFrequency(owner, repo string) ([]*WeeklyStats, *Response, error) { func (s *RepositoriesService) ListCodeFrequency(owner, repo string) ([]*WeeklyStats, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo) u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo)
@ -152,11 +158,10 @@ func (r RepositoryParticipation) String() string {
// The array order is oldest week (index 0) to most recent week. // The array order is oldest week (index 0) to most recent week.
// //
// If this is the first time these statistics are requested for the given // If this is the first time these statistics are requested for the given
// repository, this method will return a non-nil error and a status code
// of 202. This is because this is the status that github returns to
// signify that it is now computing the requested statistics. A follow
// up request, after a delay of a second or so, should result in a
// successful request.
// repository, this method will return an *AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request.
// //
// GitHub API Docs: https://developer.github.com/v3/repos/statistics/#participation // GitHub API Docs: https://developer.github.com/v3/repos/statistics/#participation
func (s *RepositoriesService) ListParticipation(owner, repo string) (*RepositoryParticipation, *Response, error) { func (s *RepositoriesService) ListParticipation(owner, repo string) (*RepositoryParticipation, *Response, error) {
@ -185,6 +190,12 @@ type PunchCard struct {
// ListPunchCard returns the number of commits per hour in each day. // ListPunchCard returns the number of commits per hour in each day.
// //
// If this is the first time these statistics are requested for the given
// repository, this method will return an *AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it is now computing the requested statistics. A follow up request, after a
// delay of a second or so, should result in a successful request.
//
// GitHub API Docs: https://developer.github.com/v3/repos/statistics/#punch-card // GitHub API Docs: https://developer.github.com/v3/repos/statistics/#punch-card
func (s *RepositoriesService) ListPunchCard(owner, repo string) ([]*PunchCard, *Response, error) { func (s *RepositoriesService) ListPunchCard(owner, repo string) ([]*PunchCard, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo) u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo)


Loading…
Cancel
Save