diff --git a/README.md b/README.md index 627966f..7791c15 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ There are several ways you can integrate `reply` into your application. Below, y // (Optional) Create a error manifest, to hold correlating error as string and it's manifest // item baseManifest := []reply.ErrorManifest{ - {"example-404-error": reply.ErrorManifestItem{Message: "resource not found", StatusCode: http.StatusNotFound}}, + {"example-404-error": reply.ErrorManifestItem{Title: "resource not found", StatusCode: http.StatusNotFound}}, } // Create replier to manage the responses going back to consumer(s) @@ -91,9 +91,12 @@ When the endpoint linked to the handler above is called, you should see the foll ```JSON { - "status": { - "message": "resource not found" + "errors": [ + { + "title": "resource not found", + "status": "404" } + ] } ``` @@ -144,6 +147,8 @@ When the endpoint linked to the handler above is called, you should see the foll ### Transfer Objects +### TODO: Update to include newly added `Transfer Object Error` + A `Transfer object` defines the shape of the response. if desired, users can create their own `transfer object` with additional logic, but it must satisfy the following interface: ```go @@ -213,7 +218,7 @@ To create an `error` response use the following code snippet: ```go // create error manifest baseManifest := []reply.ErrorManifest{ - {"example-404-error": reply.ErrorManifestItem{Message: "resource not found", StatusCode: http.StatusNotFound}}, + {"example-404-error": reply.ErrorManifestItem{Title: "resource not found", StatusCode: http.StatusNotFound}}, } // create replier based on error manifest @@ -252,9 +257,12 @@ _ = replier.NewHTTPErrorResponse(w, exampleErr, reply.WithMeta(map[string]interf ```JSON { - "status": { - "message": "resource not found" + "errors": [ + { + "title": "resource not found", + "status": "404" } + ] } ``` @@ -267,9 +275,12 @@ When a `meta` is also declared, the response will have the following format. It "meta": { "example": "meta in error reponse" }, - "status": { - "message": "resource not found" - } + "errors": [ + { + "title": "resource not found", + "status": "404" + } + ] } ``` diff --git a/examples/example_simple_api.go b/examples/example_simple_api.go index e7ff182..e3e8c8b 100644 --- a/examples/example_simple_api.go +++ b/examples/example_simple_api.go @@ -22,7 +22,7 @@ type fooReplyTransferObject struct { } type barEmbeddedExample struct { - Status *reply.TransferObjectStatus `json:"status,omitempty"` + Errors []reply.TransferObjectError `json:"errors,omitempty"` Meta map[string]interface{} `json:"meta,omitempty"` Data interface{} `json:"data,omitempty"` AccessToken string `json:"access_token,omitempty"` @@ -69,8 +69,8 @@ func (t *fooReplyTransferObject) RefreshTransferObject() reply.TransferObject { return &fooReplyTransferObject{} } -func (t *fooReplyTransferObject) SetStatus(transferObjectStatus *reply.TransferObjectStatus) { - t.Bar.Status = transferObjectStatus +func (t *fooReplyTransferObject) SetErrors(transferObjectErrors []reply.TransferObjectError) { + t.Bar.Errors = transferObjectErrors } //////////////////// @@ -81,7 +81,7 @@ type user struct { } var baseManifest []reply.ErrorManifest = []reply.ErrorManifest{ - {"example-404-error": reply.ErrorManifestItem{Message: "resource not found", StatusCode: http.StatusNotFound}}, + {"example-404-error": reply.ErrorManifestItem{Title: "resource not found", StatusCode: http.StatusNotFound}}, } var replier *reply.Replier = reply.NewReplier(baseManifest) diff --git a/replier.go b/replier.go index c8070e8..deac5ff 100644 --- a/replier.go +++ b/replier.go @@ -12,6 +12,22 @@ import ( "net/http" ) +// TransferObjectError outlines expected methods of a transfer object error +type TransferObjectError interface { + SetTitle(title string) + GetTitle() string + SetDetail(detail string) + GetDetail() string + SetAbout(about string) + GetAbout() string + SetStatusCode(status int) + GetStatusCode() string + SetCode(code string) + GetCode() string + SetMeta(meta interface{}) + GetMeta() interface{} +} + // TransferObject outlines expected methods of a transfer object type TransferObject interface { SetHeaders(headers map[string]string) @@ -22,7 +38,7 @@ type TransferObject interface { GetWriter() http.ResponseWriter GetStatusCode() int SetWriter(writer http.ResponseWriter) - SetStatus(transferObjectStatus *TransferObjectStatus) + SetErrors(transferObjectErrors []TransferObjectError) RefreshTransferObject() TransferObject SetData(data interface{}) } @@ -157,16 +173,29 @@ func (r *Replier) generateErrorResponse(err error) error { log.Printf("reply/error-response: failed to find error manifest item for %v", err) } - transferObjectStatus := &TransferObjectStatus{} - transferObjectStatus.SetMessage(manifestItem.Message) + transferObjectErrors := append([]TransferObjectError{}, ConvertErrorItemToTransferObjectError(manifestItem)) // Overwrite status code r.transferObject.SetStatusCode(manifestItem.StatusCode) - r.transferObject.SetStatus(transferObjectStatus) + r.transferObject.SetErrors(transferObjectErrors) return sendHTTPResponse(r.transferObject.GetWriter(), r.transferObject) } +// ConvertErrorItemToTransferObjectError converts manifest item to valid +// transfer object error +func ConvertErrorItemToTransferObjectError(errorItem ErrorManifestItem) TransferObjectError { + convertedError := Error{} + convertedError.SetTitle(errorItem.Title) + convertedError.SetDetail(errorItem.Detail) + convertedError.SetAbout(errorItem.About) + convertedError.SetCode(errorItem.Code) + convertedError.SetStatusCode(errorItem.StatusCode) + convertedError.SetMeta(errorItem.Meta) + + return &convertedError +} + // setUniversalAttributes sets the attributes that are common across all // response types func (r *Replier) setUniversalAttributes(writer http.ResponseWriter, headers map[string]string, meta map[string]interface{}, statusCode int) { @@ -240,7 +269,7 @@ func getManifestItems(manifest ErrorManifest, finalManifest ErrorManifest) { // getInternalServertErrorManifestItem returns typical 500 error with text and message func getInternalServertErrorManifestItem() ErrorManifestItem { - return ErrorManifestItem{Message: "Internal Server Error", StatusCode: http.StatusInternalServerError} + return ErrorManifestItem{Title: "Internal Server Error", StatusCode: http.StatusInternalServerError} } /////////////////////////////////////////////////