Skip to content

Commit

Permalink
improve handling of nil responses and responses with malformed headers
Browse files Browse the repository at this point in the history
  • Loading branch information
manicminer committed Mar 19, 2024
1 parent 95562d4 commit a5e761f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 11 deletions.
33 changes: 22 additions & 11 deletions sdk/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,22 +167,33 @@ func (r *Response) Unmarshal(model interface{}) error {
if model == nil {
return fmt.Errorf("model was nil")
}
if r.Response == nil {
return fmt.Errorf("could not unmarshal as the HTTP response was nil")
}

var contentType string
if r.Response.Header != nil {
contentType = strings.ToLower(r.Response.Header.Get("Content-Type"))

contentType := strings.ToLower(r.Header.Get("Content-Type"))
if contentType == "" {
// some APIs (e.g. Storage Data Plane) don't return a content type... so we'll assume from the Accept header
acc, err := accept.FromString(r.Request.Header.Get("Accept"))
if err != nil {
if preferred := acc.FirstChoice(); preferred != nil {
contentType = preferred.ContentType
}
}
if contentType == "" {
// fall back on request media type
contentType = strings.ToLower(r.Request.Header.Get("Content-Type"))
// some APIs (e.g. Storage Data Plane) don't return a content type... so we'll assume from the Accept header
acc, err := accept.FromString(r.Request.Header.Get("Accept"))
if err != nil {
if preferred := acc.FirstChoice(); preferred != nil {
contentType = preferred.ContentType
}
}
if contentType == "" {
// fall back on request media type
contentType = strings.ToLower(r.Request.Header.Get("Content-Type"))
}
}
}

if contentType == "" {
return fmt.Errorf("could not determine Content-Type for response")
}

// Some APIs (e.g. Maintenance) return 200 without a body, don't unmarshal these
if r.ContentLength == 0 && (r.Body == nil || r.Body == http.NoBody) {
return nil
Expand Down
32 changes: 32 additions & 0 deletions sdk/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,38 @@ func TestUnmarshalXml(t *testing.T) {
}
}

func TestUnmarshalNilHeaders(t *testing.T) {
expected := []byte("any payload")
r := &Response{
Response: &http.Response{
Header: nil,
Body: io.NopCloser(bytes.NewReader(expected)),
},
}
var unmarshaled []byte
if err := r.Unmarshal(&unmarshaled); err != nil {
if err.Error() != "could not determine Content-Type for response" {
t.Fatalf("unexpected error when unmarshaling: %+v", err)
}
} else {
t.Fatalf("expected an error but got no error")
}
}

func TestUnmarshalNilResponse(t *testing.T) {
r := &Response{
Response: nil,
}
var unmarshaled = make([]byte, 0)
if err := r.Unmarshal(&unmarshaled); err != nil {
if err.Error() != "could not unmarshal as the HTTP response was nil" {
t.Fatalf("unexpected error when unmarshaling: %+v", err)
}
} else {
t.Fatalf("expected an error but got no error")
}
}

func unmarshalResponse(body io.ReadCloser, unmarshal func(in []byte) error) error {
respBody, err := io.ReadAll(body)
if err != nil {
Expand Down

0 comments on commit a5e761f

Please sign in to comment.