Skip to content

Commit

Permalink
Added a new interface for TO errors and created conversion func.
Browse files Browse the repository at this point in the history
- Updated example API to use new models
- Initial README update
  • Loading branch information
Leon Silcott committed Sep 9, 2021
1 parent 0fdaccf commit b990709
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 18 deletions.
29 changes: 20 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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"
}
]
}
```

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"
}
]
}
```

Expand All @@ -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"
}
]
}
```

Expand Down
8 changes: 4 additions & 4 deletions examples/example_simple_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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
}

////////////////////
Expand All @@ -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)
Expand Down
39 changes: 34 additions & 5 deletions replier.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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{})
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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}
}

/////////////////////////////////////////////////
Expand Down

0 comments on commit b990709

Please sign in to comment.