Skip to content

Commit

Permalink
Add error handling for TooManyRequests API responses
Browse files Browse the repository at this point in the history
[#147953573]

Signed-off-by: Saman Alvi <[email protected]>
  • Loading branch information
Harlie Levine authored and pivotal-saman-alvi committed Jul 10, 2017
1 parent ae97481 commit fc8a1ab
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 11 deletions.
16 changes: 16 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,19 @@ func newErrUnavailableForLegalReasons(message string) ErrUnavailableForLegalReas
Message: message,
}
}

type ErrTooManyRequests struct {
ResponseCode int `json:"response_code" yaml:"response_code"`
Message string `json:"message" yaml:"message"`
}

func (e ErrTooManyRequests) Error() string {
return e.Message
}

func newErrTooManyRequests() ErrTooManyRequests {
return ErrTooManyRequests{
ResponseCode: http.StatusTooManyRequests,
Message: "You have hit a rate limit for this request",
}
}
4 changes: 4 additions & 0 deletions pivnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ func (c Client) handleUnexpectedResponse(resp *http.Response) error {
return err
}

if resp.StatusCode == http.StatusTooManyRequests {
return newErrTooManyRequests()
}

// We have to handle 500 differently because it has a different structure
if resp.StatusCode == http.StatusInternalServerError {
var internalServerError pivnetInternalServerErr
Expand Down
41 changes: 31 additions & 10 deletions pivnet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,25 @@ var _ = Describe("PivnetClient", func() {
})
})

Context("when making the request fails with error", func() {
It("forwards the error", func() {
newClientConfig.Host = "https://not-a-real-url.com"
client = pivnet.NewClient(newClientConfig, fakeLogger)
Context("when Pivnet returns a 401", func() {
var (
body []byte
)

BeforeEach(func() {
body = []byte(`{"message":"foo message"}`)
})

It("returns an ErrUnauthorized error with message from Pivnet", func() {
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest(
"GET",
fmt.Sprintf("%s/foo", apiPrefix),
),
ghttp.RespondWith(http.StatusUnauthorized, body),
),
)

_, err := client.MakeRequest(
"GET",
Expand All @@ -199,16 +214,22 @@ var _ = Describe("PivnetClient", func() {
nil,
)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(
pivnet.ErrUnauthorized{
ResponseCode: http.StatusUnauthorized,
Message: "foo message",
},
))
})
})

Context("when Pivnet returns a 401", func() {
Context("when Pivnet returns a 429", func() {
var (
body []byte
)

BeforeEach(func() {
body = []byte(`{"message":"foo message"}`)
body = []byte(`Retry later`)
})

It("returns an ErrUnauthorized error with message from Pivnet", func() {
Expand All @@ -218,7 +239,7 @@ var _ = Describe("PivnetClient", func() {
"GET",
fmt.Sprintf("%s/foo", apiPrefix),
),
ghttp.RespondWith(http.StatusUnauthorized, body),
ghttp.RespondWith(http.StatusTooManyRequests, body),
),
)

Expand All @@ -230,9 +251,9 @@ var _ = Describe("PivnetClient", func() {
)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(
pivnet.ErrUnauthorized{
ResponseCode: http.StatusUnauthorized,
Message: "foo message",
pivnet.ErrTooManyRequests{
ResponseCode: http.StatusTooManyRequests,
Message: "You have hit a rate limit for this request",
},
))
})
Expand Down
7 changes: 6 additions & 1 deletion product_files.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,12 @@ func (p ProductFilesService) Create(config CreateProductFileConfig) (ProductFile
bytes.NewReader(b),
)
if err != nil {
return ProductFile{}, err
_, ok := err.(ErrTooManyRequests)
if ok {
return ProductFile{}, fmt.Errorf("You have hit the file creation limit. Please wait before creating more files. Contact [email protected] with additional questions.")
} else {
return ProductFile{}, err
}
}
defer resp.Body.Close()

Expand Down
18 changes: 18 additions & 0 deletions product_files_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,24 @@ var _ = Describe("PivnetClient - product files", func() {
})
})

Context("when the server responds with a 429 status code", func() {
It("returns an error indicating the limit was hit", func() {
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", fmt.Sprintf(
"%s/products/%s/product_files",
apiPrefix,
productSlug,
)),
ghttp.RespondWith(http.StatusTooManyRequests, "Retry later"),
),
)

_, err := client.ProductFiles.Create(createProductFileConfig)
Expect(err.Error()).To(ContainSubstring("You have hit the file creation limit. Please wait before creating more files. Contact [email protected] with additional questions."))
})
})

Context("when the json unmarshalling fails with error", func() {
It("forwards the error", func() {
server.AppendHandlers(
Expand Down

0 comments on commit fc8a1ab

Please sign in to comment.