Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Content-Length checking before decoding #63

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 8 additions & 7 deletions sling.go
Expand Up @@ -360,9 +360,9 @@ func (s *Sling) ReceiveSuccess(successV interface{}) (*http.Response, error) {
// Receive creates a new HTTP request and returns the response. Success
// responses (2XX) are JSON decoded into the value pointed to by successV and
// other responses are JSON decoded into the value pointed to by failureV.
// If the status code of response is 204(no content), decoding is skipped.
// Any error creating the request, sending it, or decoding the response is
// returned.
// If the status code of response is 204(no content) or the Content-Lenght is 0,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case it's helpful to you, please note there's a typo in "Content-Lenght". It should be "Content-Length".

// decoding is skipped. Any error creating the request, sending it, or decoding
// the response is returned.
// Receive is shorthand for calling Request and Do.
func (s *Sling) Receive(successV, failureV interface{}) (*http.Response, error) {
req, err := s.Request()
Expand All @@ -375,8 +375,9 @@ func (s *Sling) Receive(successV, failureV interface{}) (*http.Response, error)
// Do sends an HTTP request and returns the response. Success responses (2XX)
// are JSON decoded into the value pointed to by successV and other responses
// are JSON decoded into the value pointed to by failureV.
// If the status code of response is 204(no content), decoding is skipped.
// Any error sending the request or decoding the response is returned.
// If the status code of response is 204(no content) or the Content-Length is 0,
// decoding is skipped. Any error sending the request or decoding the response
// is returned.
func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Response, error) {
resp, err := s.httpClient.Do(req)
if err != nil {
Expand All @@ -391,8 +392,8 @@ func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Res
// See: https://golang.org/pkg/net/http/#Response
defer io.Copy(ioutil.Discard, resp.Body)

// Don't try to decode on 204s
if resp.StatusCode == http.StatusNoContent {
// Don't try to decode on 204s or Content-Length is 0
if resp.StatusCode == http.StatusNoContent || resp.ContentLength == 0 {
return resp, nil
}

Expand Down
32 changes: 32 additions & 0 deletions sling_test.go
Expand Up @@ -828,6 +828,38 @@ func TestReceive_success(t *testing.T) {
}
}

func TestReceive_StatusOKNoContent(t *testing.T) {
client, mux, server := testServer()
defer server.Close()
mux.HandleFunc("/foo/submit", func(w http.ResponseWriter, r *http.Request) {
assertMethod(t, "POST", r)
w.WriteHeader(201)
w.Header().Set("Location", "/foo/latest")
})

endpoint := New().Client(client).Base("http://example.com/").Path("foo/").Post("submit")
// fake a post response for testing purposes, checking that it's valid happens in other tests
params := FakeParams{}
model := new(FakeModel)
apiError := new(APIError)
resp, err := endpoint.New().BodyForm(params).Receive(model, apiError)

if err != nil {
t.Errorf("expected nil, got %v", err)
}
if resp.StatusCode != 201 {
t.Errorf("expected %d, got %d", 201, resp.StatusCode)
}
expectedModel := &FakeModel{}
if !reflect.DeepEqual(expectedModel, model) {
t.Errorf("expected %v, got %v", expectedModel, model)
}
expectedAPIError := &APIError{}
if !reflect.DeepEqual(expectedAPIError, apiError) {
t.Errorf("failureV should be zero valued, exepcted %v, got %v", expectedAPIError, apiError)
}
}

func TestReceive_failure(t *testing.T) {
client, mux, server := testServer()
defer server.Close()
Expand Down