Skip to content

Commit

Permalink
extract details from response (#399)
Browse files Browse the repository at this point in the history
* extract details from response

* add tests for extracting details from body

* make lll linter happy

* extract details from body after processing by status code
  • Loading branch information
randmonkey committed Jan 16, 2024
1 parent b34bcbb commit 19b8bfa
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
- [0.2.0](#020)
- [0.1.0](#010)

## Unreleased

- Added extract of `details` field in response when CRUD API fails to extract
details from Konnect APIs.
[#399](https://github.com/Kong/go-kong/pull/399)

## [v0.50.0]

> Release date: 2024/01/09
Expand Down
21 changes: 19 additions & 2 deletions kong/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ func messageFromBody(b []byte) string {
return s.Message
}

// detailsFromBodyDetailsField extract details from body if the response body contains a "details" field.
// Used for extracting details from response from Konnect APIs when error happens.
func detailsFromBodyDetailsField(b []byte) any {
s := struct {
Details any `json:"details"`
}{}
if err := json.Unmarshal(b, &s); err != nil {
return nil
}
return s.Details
}

func hasError(res *http.Response) error {
if res.StatusCode >= 200 && res.StatusCode <= 399 {
return nil
Expand All @@ -48,18 +60,23 @@ func hasError(res *http.Response) error {
}

apiErr := NewAPIError(res.StatusCode, messageFromBody(body))
if details, ok := extractErrDetails(res); ok {
if details, ok := extractErrDetails(res, body); ok {
apiErr.SetDetails(details)
}

return apiErr
}

func extractErrDetails(res *http.Response) (any, bool) {
func extractErrDetails(res *http.Response, body []byte) (any, bool) {
// firstly deal with certain status code.
switch res.StatusCode {
case http.StatusTooManyRequests:
return extractErrTooManyRequestsDetails(res)
}
// Then extract details from "details" field in the response body.
if detailsFromRespBody := detailsFromBodyDetailsField(body); detailsFromRespBody != nil {
return detailsFromRespBody, true
}

return nil, false
}
Expand Down
19 changes: 19 additions & 0 deletions kong/response_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,25 @@ func TestHasError(T *testing.T) {
message: "<failed to parse response body: invalid character 'T' looking for beginning of value>",
},
},
{
name: "code 400 and has array of objects in 'details' in response",
response: http.Response{
StatusCode: 400,
Body: io.NopCloser(strings.NewReader(
`{"message":"validation failed","details":[{"type":"ERROR_TYPE_FIELD","field":"config.key"}]}`,
)),
},
want: &APIError{
httpCode: 400,
message: "validation failed",
details: []any{
map[string]any{
"type": "ERROR_TYPE_FIELD",
"field": "config.key",
},
},
},
},
{
name: "code 429 with retry-after header",
response: http.Response{
Expand Down

0 comments on commit 19b8bfa

Please sign in to comment.