Files
threshold/api/response.go
T
Jeff Mitchell 4690225c1e Update delete action behavior and JSON format output (#1155)
This PR changes delete behavior:

* On success, a 204 is returned rather than a 200 with an empty JSON object
* The CLI now passes through the 404 error if encountered instead of swallowing it

It also updates formatting for JSON to use the response body, which means that the item (or items) in the JSON format are actually the format across the wire, instead of being reinterpreted by unmarshaling into the Go SDK and then remarshaling.
2021-04-26 20:38:55 -04:00

82 lines
2.0 KiB
Go

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
Map map[string]interface{}
}
// HttpResponse returns the underlying HTTP response
func (r *Response) HttpResponse() *http.Response {
return r.resp
}
// StatusCode returns the underlying HTTP status code
func (r *Response) StatusCode() int {
return r.resp.StatusCode
}
func (r *Response) Decode(inStruct interface{}) (*Error, error) {
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)
if r.resp.StatusCode == 204 {
// Do nothing.
return nil, nil
}
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)
}
if r.Body.Len() > 0 {
reader := bytes.NewReader(r.Body.Bytes())
dec := json.NewDecoder(reader)
dec.UseNumber()
r.Map = make(map[string]interface{})
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())
}
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())
}
}
}
}
if r.resp.StatusCode >= 400 {
apiErr := inStruct.(*Error)
apiErr.response = r
return apiErr, nil
}
return nil, nil
}