From 20b1469456c5f7b7bdbc994556eacc1ffeda5e8d Mon Sep 17 00:00:00 2001 From: Derek Dowling Date: Wed, 2 Dec 2015 17:24:22 -0800 Subject: [PATCH] Fixing client object prepare bug for POST request missing ID --- client.go | 2 +- client_test.go | 4 ++-- error.go | 6 +++--- list.go | 2 +- list_test.go | 2 +- object.go | 15 ++++++++++----- object_test.go | 10 +++++----- response.go | 8 ++++---- 8 files changed, 27 insertions(+), 22 deletions(-) diff --git a/client.go b/client.go index 5d7eb61..3f48034 100644 --- a/client.go +++ b/client.go @@ -126,7 +126,7 @@ func NewRequest(method string, urlStr string, object *Object) (*Request, error) // use Prepare to generate a payload if object != nil { - payload, err := object.Prepare(request) + payload, err := object.prepare(request, false) if err != nil { return nil, fmt.Errorf("Error preparing object: %s", err.Error()) } diff --git a/client_test.go b/client_test.go index ed50b79..d4201f3 100644 --- a/client_test.go +++ b/client_test.go @@ -131,7 +131,7 @@ func mockClientObjectResponse(object *Object) (*http.Response, error) { return nil, err } - resp, err := object.Prepare(req.Request) + resp, err := object.prepare(req.Request, false) if err != nil { return nil, err } @@ -148,7 +148,7 @@ func mockClientListResponse(list *List) (*http.Response, error) { return nil, err } - resp, err := list.Prepare(req.Request) + resp, err := list.prepare(req.Request, false) if err != nil { return nil, err } diff --git a/error.go b/error.go index 9d207d7..6d2305b 100644 --- a/error.go +++ b/error.go @@ -45,9 +45,9 @@ func (e *Error) Error() string { // Prepare returns a response containing a prepared error list since the JSON // API specification requires that errors are returned as a list -func (e *Error) Prepare(req *http.Request) (*Response, SendableError) { +func (e *Error) prepare(req *http.Request, response bool) (*Response, SendableError) { list := &ErrorList{Errors: []*Error{e}} - return list.Prepare(req) + return list.prepare(req, response) } // ErrorList is just a wrapped error array that implements Sendable @@ -76,7 +76,7 @@ func (e *ErrorList) Add(newError *Error) *Error { } // Prepare first validates the errors, and then returns an appropriate response -func (e *ErrorList) Prepare(req *http.Request) (*Response, SendableError) { +func (e *ErrorList) prepare(req *http.Request, response bool) (*Response, SendableError) { if len(e.Errors) == 0 { return nil, ISE("No errors provided for attempted error response.") } diff --git a/list.go b/list.go index 555eb63..a364fc5 100644 --- a/list.go +++ b/list.go @@ -8,7 +8,7 @@ type List struct { } // Prepare returns a success status response -func (l *List) Prepare(r *http.Request) (*Response, SendableError) { +func (l *List) prepare(r *http.Request, response bool) (*Response, SendableError) { return &Response{Data: l.Objects, HTTPStatus: http.StatusOK}, nil } diff --git a/list_test.go b/list_test.go index ff5c588..edd05d0 100644 --- a/list_test.go +++ b/list_test.go @@ -24,7 +24,7 @@ func TestList(t *testing.T) { req := &http.Request{} Convey("->Prepare()", func() { - response, err := testList.Prepare(req) + response, err := testList.prepare(req, true) So(err, ShouldBeNil) So(response.HTTPStatus, ShouldEqual, http.StatusOK) }) diff --git a/object.go b/object.go index a3c58fa..494e32e 100644 --- a/object.go +++ b/object.go @@ -85,13 +85,18 @@ func (o *Object) Unmarshal(objType string, target interface{}) (err SendableErro // Prepare creates a new JSON single object response with an appropriate HTTP status // to match the request method type. -func (o *Object) Prepare(r *http.Request) (*Response, SendableError) { +func (o *Object) prepare(r *http.Request, response bool) (*Response, SendableError) { - if len(o.ID) == 0 { - return nil, SpecificationError("ID must be set for Object response") + if o.ID == "" { + + // don't error if the client is attempting to performing a POST request, in + // which case, ID shouldn't actually be set + if !response && r.Method != "POST" { + return nil, SpecificationError("ID must be set for Object response") + } } - if len(o.Type) == 0 { + if o.Type == "" { return nil, SpecificationError("Type must be set for Object response") } var status int @@ -109,7 +114,7 @@ func (o *Object) Prepare(r *http.Request) (*Response, SendableError) { return SpecificationError(fmt.Sprintf( "The JSON Specification does not accept '%s' requests.", r.Method, - )).Prepare(r) + )).prepare(r, response) } return &Response{HTTPStatus: status, Data: o}, nil diff --git a/object_test.go b/object_test.go index f30f282..58f5c1a 100644 --- a/object_test.go +++ b/object_test.go @@ -106,32 +106,32 @@ func TestObject(t *testing.T) { }) }) - Convey("->Prepare()", func() { + Convey("->prepare()", func() { Convey("should handle a POST response correctly", func() { request.Method = "POST" - resp, err := testObject.Prepare(request) + resp, err := testObject.prepare(request, true) So(err, ShouldBeNil) So(resp.HTTPStatus, ShouldEqual, http.StatusCreated) }) Convey("should handle a GET response correctly", func() { request.Method = "GET" - resp, err := testObject.Prepare(request) + resp, err := testObject.prepare(request, true) So(err, ShouldBeNil) So(resp.HTTPStatus, ShouldEqual, http.StatusOK) }) Convey("should handle a PATCH response correctly", func() { request.Method = "PATCH" - resp, err := testObject.Prepare(request) + resp, err := testObject.prepare(request, true) So(err, ShouldBeNil) So(resp.HTTPStatus, ShouldEqual, http.StatusOK) }) Convey("should return a formatted Error for an unsupported method Type", func() { request.Method = "PUT" - resp, err := testObject.Prepare(request) + resp, err := testObject.prepare(request, true) So(err, ShouldBeNil) So(resp.HTTPStatus, ShouldEqual, http.StatusNotAcceptable) }) diff --git a/response.go b/response.go index f8603ae..b0596ba 100644 --- a/response.go +++ b/response.go @@ -14,7 +14,7 @@ const JSONAPIVersion = "1.1" // Sendable implements functions that allows different response types // to produce a sendable JSON Response format type Sendable interface { - Prepare(r *http.Request) (*Response, SendableError) + prepare(r *http.Request, response bool) (*Response, SendableError) } // Response represents the top level json format of incoming requests @@ -57,9 +57,9 @@ func (r *Response) Validate() SendableError { // Send fires a JSON response if the payload is prepared successfully, otherwise it // returns an Error which can also be sent. func Send(w http.ResponseWriter, r *http.Request, payload Sendable) { - response, err := payload.Prepare(r) + response, err := payload.prepare(r, true) if err != nil { - response, err = err.Prepare(r) + response, err = err.prepare(r, true) // If we ever hit this, something seriously wrong has happened if err != nil { @@ -78,7 +78,7 @@ func SendResponse(w http.ResponseWriter, r *http.Request, response *Response) { err := response.Validate() if err != nil { - response, err = err.Prepare(r) + response, err = err.prepare(r, true) // If we ever hit this, something seriously wrong has happened if err != nil {