diff --git a/sling.go b/sling.go index fe9c54e..cc4ecc1 100644 --- a/sling.go +++ b/sling.go @@ -359,6 +359,7 @@ 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. // Receive is shorthand for calling Request and Do. @@ -373,6 +374,7 @@ 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. func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Response, error) { resp, err := s.httpClient.Do(req) @@ -383,7 +385,7 @@ func (s *Sling) Do(req *http.Request, successV, failureV interface{}) (*http.Res defer resp.Body.Close() // Don't try to decode on 204s - if resp.StatusCode == 204 { + if resp.StatusCode == http.StatusNoContent { return resp, nil } diff --git a/sling_test.go b/sling_test.go index 5fa70fc..b6f3b12 100644 --- a/sling_test.go +++ b/sling_test.go @@ -665,6 +665,36 @@ func TestDo_onSuccessWithNilValue(t *testing.T) { } } +func TestDo_noContent(t *testing.T) { + client, mux, server := testServer() + defer server.Close() + mux.HandleFunc("/nocontent", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(204) + }) + + sling := New().Client(client) + req, _ := http.NewRequest("DELETE", "http://example.com/nocontent", nil) + + model := new(FakeModel) + apiError := new(APIError) + resp, err := sling.Do(req, model, apiError) + + if err != nil { + t.Errorf("expected nil, got %v", err) + } + if resp.StatusCode != 204 { + t.Errorf("expected %d, got %d", 204, resp.StatusCode) + } + expectedModel := &FakeModel{} + if !reflect.DeepEqual(expectedModel, model) { + t.Errorf("successV should not be populated, exepcted %v, got %v", expectedModel, model) + } + expectedAPIError := &APIError{} + if !reflect.DeepEqual(expectedAPIError, apiError) { + t.Errorf("failureV should not be populated, exepcted %v, got %v", expectedAPIError, apiError) + } +} + func TestDo_onFailure(t *testing.T) { const expectedMessage = "Invalid argument" const expectedCode int = 215 @@ -830,6 +860,25 @@ func TestReceive_failure(t *testing.T) { } } +func TestReceive_noContent(t *testing.T) { + client, mux, server := testServer() + defer server.Close() + mux.HandleFunc("/foo/submit", func(w http.ResponseWriter, r *http.Request) { + assertMethod(t, "HEAD", r) + w.WriteHeader(204) + }) + + endpoint := New().Client(client).Base("http://example.com/").Path("foo/").Head("submit") + resp, err := endpoint.New().Receive(nil, nil) + + if err != nil { + t.Errorf("expected nil, got %v", err) + } + if resp.StatusCode != 204 { + t.Errorf("expected %d, got %d", 204, resp.StatusCode) + } +} + func TestReceive_errorCreatingRequest(t *testing.T) { expectedErr := errors.New("json: unsupported value: +Inf") resp, err := New().BodyJSON(FakeModel{Temperature: math.Inf(1)}).Receive(nil, nil)