Skip to content

Commit

Permalink
Fixing client object prepare bug for POST request missing ID
Browse files Browse the repository at this point in the history
  • Loading branch information
Derek Dowling committed Dec 3, 2015
1 parent ce2afa4 commit 20b1469
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 22 deletions.
2 changes: 1 addition & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Expand Down
4 changes: 2 additions & 2 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.")
}
Expand Down
2 changes: 1 addition & 1 deletion list.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
2 changes: 1 addition & 1 deletion list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
Expand Down
15 changes: 10 additions & 5 deletions object.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
10 changes: 5 additions & 5 deletions object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
Expand Down
8 changes: 4 additions & 4 deletions response.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down

0 comments on commit 20b1469

Please sign in to comment.