From 2e9eb16c7b0b390fa41baedb3c4da03073b8ca8c Mon Sep 17 00:00:00 2001 From: Dragomir Ivanov Date: Wed, 13 May 2020 22:29:48 +0300 Subject: [PATCH] Keep propagation of root error, instead of wrapped `rest.Error` --- rest/errors.go | 22 +++++++++++----------- rest/method_delete.go | 4 ++-- rest/method_get.go | 8 ++++---- rest/method_item_delete.go | 8 ++++---- rest/method_item_get.go | 8 ++++---- rest/method_item_patch.go | 28 ++++++++++++++-------------- rest/method_item_put.go | 32 ++++++++++++++++---------------- rest/method_post.go | 24 ++++++++++++------------ 8 files changed, 67 insertions(+), 67 deletions(-) diff --git a/rest/errors.go b/rest/errors.go index 994f5fd1..2ae4c8b5 100644 --- a/rest/errors.go +++ b/rest/errors.go @@ -47,29 +47,29 @@ type Error struct { // NewError returns a rest.Error from an standard error. // // If the the inputted error is recognized, the appropriate rest.Error is mapped. -func NewError(err error) *Error { +func NewError(err error) (error, int) { if Err, ok := err.(*Error); ok { - return Err + return err, Err.Code } switch err { case context.Canceled: - return ErrClientClosedRequest + return ErrClientClosedRequest, ErrClientClosedRequest.Code case context.DeadlineExceeded: - return ErrGatewayTimeout + return ErrGatewayTimeout, ErrGatewayTimeout.Code case resource.ErrNotFound: - return ErrNotFound + return ErrNotFound, ErrNotFound.Code case resource.ErrForbidden: - return ErrForbidden + return ErrForbidden, ErrForbidden.Code case resource.ErrConflict: - return ErrConflict + return ErrConflict, ErrConflict.Code case resource.ErrNotImplemented: - return ErrNotImplemented + return ErrNotImplemented, ErrNotImplemented.Code case resource.ErrNoStorage: - return &Error{501, err.Error(), nil} + return &Error{501, err.Error(), nil}, 501 case nil: - return nil + return nil, 0 default: - return &Error{520, err.Error(), nil} + return err, 520 } } diff --git a/rest/method_delete.go b/rest/method_delete.go index 82cb8e01..9bd048f8 100644 --- a/rest/method_delete.go +++ b/rest/method_delete.go @@ -14,8 +14,8 @@ func listDelete(ctx context.Context, r *http.Request, route *RouteMatch) (status } total, err := route.Resource().Clear(ctx, q) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } headers = http.Header{} headers.Set("X-Total", strconv.Itoa(total)) diff --git a/rest/method_get.go b/rest/method_get.go index f4d269c2..6de8e6be 100644 --- a/rest/method_get.go +++ b/rest/method_get.go @@ -36,8 +36,8 @@ func listGet(ctx context.Context, r *http.Request, route *RouteMatch) (status in list, err = rsc.Find(ctx, q) } if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } if win := q.Window; win != nil && win.Offset > 0 { list.Offset = win.Offset @@ -45,8 +45,8 @@ func listGet(ctx context.Context, r *http.Request, route *RouteMatch) (status in for _, item := range list.Items { item.Payload, err = q.Projection.Eval(ctx, item.Payload, restResource{rsc}) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } } return 200, nil, list diff --git a/rest/method_item_delete.go b/rest/method_item_delete.go index 77ebe1d0..1640de25 100644 --- a/rest/method_item_delete.go +++ b/rest/method_item_delete.go @@ -16,8 +16,8 @@ func itemDelete(ctx context.Context, r *http.Request, route *RouteMatch) (status q.Window = &query.Window{Limit: 1} l, err := route.Resource().Find(ctx, q) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } if len(l.Items) == 0 { return ErrNotFound.Code, nil, ErrNotFound @@ -28,8 +28,8 @@ func itemDelete(ctx context.Context, r *http.Request, route *RouteMatch) (status return err.Code, nil, err } if err := route.Resource().Delete(ctx, original); err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } return 204, nil, nil } diff --git a/rest/method_item_get.go b/rest/method_item_get.go index 28900736..071e8d2f 100644 --- a/rest/method_item_get.go +++ b/rest/method_item_get.go @@ -18,8 +18,8 @@ func itemGet(ctx context.Context, r *http.Request, route *RouteMatch) (status in q.Window = &query.Window{Limit: 1} list, err := rsrc.Find(ctx, q) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } else if len(list.Items) == 0 { return ErrNotFound.Code, nil, ErrNotFound } @@ -40,8 +40,8 @@ func itemGet(ctx context.Context, r *http.Request, route *RouteMatch) (status in } item.Payload, err = q.Projection.Eval(ctx, item.Payload, restResource{rsrc}) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } return 200, nil, item } diff --git a/rest/method_item_patch.go b/rest/method_item_patch.go index dfbc0640..db5f1b49 100644 --- a/rest/method_item_patch.go +++ b/rest/method_item_patch.go @@ -48,8 +48,8 @@ func itemPatch(ctx context.Context, r *http.Request, route *RouteMatch) (status q.Window = &query.Window{Limit: 1} if l, err := rsrc.Find(ctx, q); err != nil { // If item can't be fetch, return an error. - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } else if len(l.Items) == 0 { return ErrNotFound.Code, nil, ErrNotFound } else { @@ -96,21 +96,21 @@ func itemPatch(ctx context.Context, r *http.Request, route *RouteMatch) (status } item, err := resource.NewItem(doc) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } preHookEtag := item.ETag if len(q.Projection) > 0 { projected, err := q.Projection.Eval(ctx, item.Payload, restResource{rsrc}) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } preHookEtag, err = resource.GenEtag(projected) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } } @@ -120,23 +120,23 @@ func itemPatch(ctx context.Context, r *http.Request, route *RouteMatch) (status // condition (i.e.: another thread modified the document between the Find() // and the Store()). if err = rsrc.Update(ctx, item, original); err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } postHookEtag := item.ETag // Evaluate projection so response gets the same format as read requests. item.Payload, err = q.Projection.Eval(ctx, item.Payload, restResource{rsrc}) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } if len(q.Projection) > 0 { postHookEtag, err = resource.GenEtag(item.Payload) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } } diff --git a/rest/method_item_put.go b/rest/method_item_put.go index 3f2c1d23..df5724c8 100644 --- a/rest/method_item_put.go +++ b/rest/method_item_put.go @@ -27,8 +27,8 @@ func itemPut(ctx context.Context, r *http.Request, route *RouteMatch) (status in var original *resource.Item q.Window = &query.Window{Limit: 1} if l, err := rsrc.Find(ctx, q); err != nil && err != ErrNotFound { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } else if len(l.Items) == 1 { original = l.Items[0] } @@ -79,21 +79,21 @@ func itemPut(ctx context.Context, r *http.Request, route *RouteMatch) (status in } item, err := resource.NewItem(doc) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } preHookEtag := item.ETag if len(q.Projection) > 0 { projected, err := q.Projection.Eval(ctx, item.Payload, restResource{rsrc}) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } preHookEtag, err = resource.GenEtag(projected) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } } // If we have an original item, pass it to the handler so we make sure @@ -102,13 +102,13 @@ func itemPut(ctx context.Context, r *http.Request, route *RouteMatch) (status in // is provided. if original != nil { if err = rsrc.Update(ctx, item, original); err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } } else { if err = rsrc.Insert(ctx, []*resource.Item{item}); err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } } @@ -116,15 +116,15 @@ func itemPut(ctx context.Context, r *http.Request, route *RouteMatch) (status in // Evaluate projection so response gets the same format as read requests. item.Payload, err = q.Projection.Eval(ctx, item.Payload, restResource{rsrc}) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } if len(q.Projection) > 0 { postHookEtag, err = resource.GenEtag(item.Payload) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } } diff --git a/rest/method_post.go b/rest/method_post.go index 47d0c9d8..fcb69d31 100644 --- a/rest/method_post.go +++ b/rest/method_post.go @@ -32,36 +32,36 @@ func listPost(ctx context.Context, r *http.Request, route *RouteMatch) (status i } item, err := resource.NewItem(doc) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } preHookEtag := item.ETag if len(q.Projection) > 0 { projected, err := q.Projection.Eval(ctx, item.Payload, restResource{rsrc}) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } preHookEtag, err = resource.GenEtag(projected) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } } // TODO: add support for batch insert if err = rsrc.Insert(ctx, []*resource.Item{item}); err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } postHookEtag := item.ETag // Evaluate projection so response gets the same format as read requests. item.Payload, err = q.Projection.Eval(ctx, item.Payload, restResource{rsrc}) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } // See https://www.subbu.org/blog/2008/10/location-vs-content-location headers = http.Header{} @@ -78,8 +78,8 @@ func listPost(ctx context.Context, r *http.Request, route *RouteMatch) (status i if len(q.Projection) > 0 { postHookEtag, err = resource.GenEtag(item.Payload) if err != nil { - e = NewError(err) - return e.Code, nil, e + e, code := NewError(err) + return code, nil, e } }