Files
threshold/api/response.go
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

91 lines
2.3 KiB
Go
Raw Normal View History

// Copyright IBM Corp. 2020, 2026
2020-12-07 14:25:16 -07:00
// SPDX-License-Identifier: MPL-2.0
2023-02-02 17:15:17 -08:00
2020-05-04 23:02:18 -04:00
package api
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
// Response is a custom response that wraps an HTTP response. Body will be
// populated with a buffer containing the response body after Decode is called;
// it will be nil if the response was a 204.
type Response struct {
resp *http.Response
Body *bytes.Buffer
2022-10-25 18:29:38 -05:00
Map map[string]any
2020-05-04 23:02:18 -04:00
}
// NewResponse returns a new *Response based on the provided http.Response.
// Just as when constructing the Response directly, Body and Map will be
// populated after Decode is called.
func NewResponse(r *http.Response) *Response {
return &Response{resp: r}
}
2020-05-04 23:02:18 -04:00
// HttpResponse returns the underlying HTTP response
func (r *Response) HttpResponse() *http.Response {
return r.resp
}
2021-02-25 12:39:51 -05:00
// StatusCode returns the underlying HTTP status code
func (r *Response) StatusCode() int {
return r.resp.StatusCode
}
2022-10-25 18:29:38 -05:00
func (r *Response) Decode(inStruct any) (*Error, error) {
2020-05-04 23:02:18 -04:00
if r == nil || r.resp == nil {
return nil, fmt.Errorf("nil response, cannot decode")
}
defer r.resp.Body.Close()
// Always allocate this buffer. It's okay if the bytes return `nil`.
r.Body = new(bytes.Buffer)
2020-05-04 23:02:18 -04:00
if r.resp.StatusCode == 204 {
// Do nothing.
return nil, nil
}
2020-12-07 14:25:16 -07:00
if r.resp.StatusCode >= 400 {
// If the status code is >= 400 the body of the response will be the
// json representation of the Error struct so we decode it as such.
inStruct = &Error{}
}
if r.resp.Body != nil {
r.Body = new(bytes.Buffer)
if _, err := r.Body.ReadFrom(r.resp.Body); err != nil {
return nil, fmt.Errorf("error reading response body: %w", err)
}
2020-05-04 23:02:18 -04:00
if r.Body.Len() > 0 {
reader := bytes.NewReader(r.Body.Bytes())
dec := json.NewDecoder(reader)
dec.UseNumber()
2022-10-25 18:29:38 -05:00
r.Map = make(map[string]any)
if err := dec.Decode(&r.Map); err != nil {
return nil, fmt.Errorf("error decoding response to map: %w; response was %s", err, r.Body.String())
}
2020-09-08 23:57:26 -04:00
if inStruct != nil {
reader.Seek(0, 0)
dec = json.NewDecoder(reader)
if err := dec.Decode(&inStruct); err != nil {
return nil, fmt.Errorf("error decoding response to struct: %w; response was %s", err, r.Body.String())
2020-09-08 23:57:26 -04:00
}
}
}
2020-05-04 23:02:18 -04:00
}
2020-12-07 14:25:16 -07:00
2020-05-04 23:02:18 -04:00
if r.resp.StatusCode >= 400 {
2020-12-07 14:25:16 -07:00
apiErr := inStruct.(*Error)
apiErr.response = r
return apiErr, nil
2020-05-04 23:02:18 -04:00
}
return nil, nil
}