Skip to content

Commit

Permalink
Merge pull request #1101 from openmeterio/fix/granting-bool-string
Browse files Browse the repository at this point in the history
fix: give proper error response if the errors are wrapped
  • Loading branch information
turip authored Jun 30, 2024
2 parents 11001a0 + d1c3ddf commit e11f4bc
Show file tree
Hide file tree
Showing 11 changed files with 498 additions and 530 deletions.
343 changes: 172 additions & 171 deletions api/api.gen.go

Large diffs are not rendered by default.

343 changes: 172 additions & 171 deletions api/client/go/client.gen.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/client/node/schemas/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ export interface components {
priority?: number
/**
* Format: date-time
* @description The effective time. Provided value will be ceiled to metering windowSize (minute).
* @description Effective date for grants and anchor for recurring grants. Provided value will be ceiled to metering windowSize (minute).
*
* @example 2023-01-01T00:00:00Z
*/
Expand Down
95 changes: 51 additions & 44 deletions api/client/python/src/openmeter/_operations/_operations.py

Large diffs are not rendered by default.

95 changes: 51 additions & 44 deletions api/client/python/src/openmeter/aio/_operations/_operations.py

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions api/client/web/src/client/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,16 +253,16 @@ export interface components {
createdAt: string
/**
* Format: date-time
* @description The date and time the resource was last updated.
* @description The date and time the resource was last updated. Defaults to createdAt if not updated.
* @example 2023-01-01T00:00:00Z
*/
updatedAt: string
/**
* Format: date-time
* @description The date and time the resource was deleted.
* @description The date and time the resource was deleted. Null if not deleted.
* @example 2023-01-01T00:00:00Z
*/
deletedAt: string
deletedAt?: string
}
/**
* @description Conflict
Expand Down Expand Up @@ -791,7 +791,7 @@ export interface components {
priority?: number
/**
* Format: date-time
* @description The effective time. Provided value will be ceiled to metering windowSize (minute).
* @description Effective date for grants and anchor for recurring grants. Provided value will be ceiled to metering windowSize (minute).
*
* @example 2023-01-01T00:00:00Z
*/
Expand Down
2 changes: 1 addition & 1 deletion api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1847,7 +1847,7 @@ components:
example: 1
effectiveAt:
description: |
The effective time. Provided value will be ceiled to metering windowSize (minute).
Effective date for grants and anchor for recurring grants. Provided value will be ceiled to metering windowSize (minute).
type: string
format: date-time
example: "2023-01-01T00:00:00Z"
Expand Down
63 changes: 11 additions & 52 deletions internal/entitlement/httpdriver/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,57 +14,16 @@ import (
func getErrorEncoder() httptransport.ErrorEncoder {
return func(ctx context.Context, err error, w http.ResponseWriter) bool {
// user errors
if _, ok := err.(*productcatalog.FeatureNotFoundError); ok {
commonhttp.NewHTTPError(
http.StatusNotFound,
err,
).EncodeError(ctx, w)
return true
}
if _, ok := err.(*entitlement.NotFoundError); ok {
commonhttp.NewHTTPError(
http.StatusNotFound,
err,
).EncodeError(ctx, w)
return true
}
if _, ok := err.(*models.GenericUserError); ok {
commonhttp.NewHTTPError(
http.StatusBadRequest,
err,
).EncodeError(ctx, w)
return true
}
if err, ok := err.(*entitlement.AlreadyExistsError); ok {
commonhttp.NewHTTPError(
http.StatusConflict,
err,
commonhttp.ExtendProblem("conflictingEntityId", err.EntitlementID),
).EncodeError(ctx, w)
return true
}
if err, ok := err.(*entitlement.InvalidValueError); ok {
commonhttp.NewHTTPError(
http.StatusBadRequest,
err,
).EncodeError(ctx, w)
return true
}
if err, ok := err.(*entitlement.InvalidFeatureError); ok {
commonhttp.NewHTTPError(
http.StatusBadRequest,
err,
).EncodeError(ctx, w)
return true
}
// system errors (naming known errors for transparency)
if _, ok := err.(*entitlement.WrongTypeError); ok {
commonhttp.NewHTTPError(
http.StatusInternalServerError,
err,
).EncodeError(ctx, w)
return true
}
return false
return commonhttp.HandleErrorIfTypeMatches[*productcatalog.FeatureNotFoundError](ctx, http.StatusNotFound, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*entitlement.NotFoundError](ctx, http.StatusNotFound, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*models.GenericUserError](ctx, http.StatusBadRequest, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*entitlement.AlreadyExistsError](
ctx, http.StatusConflict, err, w,
func(specificErr *entitlement.AlreadyExistsError) (string, string) {
return "conflictingEntityId", specificErr.EntitlementID
}) ||
commonhttp.HandleErrorIfTypeMatches[*entitlement.InvalidValueError](ctx, http.StatusBadRequest, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*entitlement.InvalidFeatureError](ctx, http.StatusBadRequest, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*entitlement.WrongTypeError](ctx, http.StatusBadRequest, err, w)
}
}
47 changes: 5 additions & 42 deletions internal/productcatalog/httpdriver/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,10 @@ import (

func getErrorEncoder() httptransport.ErrorEncoder {
return func(ctx context.Context, err error, w http.ResponseWriter) bool {
// user errors
if _, ok := err.(*productcatalog.FeatureNotFoundError); ok {
commonhttp.NewHTTPError(
http.StatusNotFound,
err,
).EncodeError(ctx, w)
return true
}

if _, ok := err.(*productcatalog.FeatureInvalidFiltersError); ok {
commonhttp.NewHTTPError(
http.StatusBadRequest,
err,
).EncodeError(ctx, w)
return true
}

if _, ok := err.(*productcatalog.FeatureInvalidMeterAggregationError); ok {
commonhttp.NewHTTPError(
http.StatusBadRequest,
err,
).EncodeError(ctx, w)
return true
}

if _, ok := err.(*models.MeterNotFoundError); ok {
commonhttp.NewHTTPError(
http.StatusNotFound,
err,
).EncodeError(ctx, w)
return true
}

if _, ok := err.(*productcatalog.FeatureWithNameAlreadyExistsError); ok {
commonhttp.NewHTTPError(
http.StatusConflict,
err,
).EncodeError(ctx, w)
return true
}

return false
return commonhttp.HandleErrorIfTypeMatches[*productcatalog.FeatureNotFoundError](ctx, http.StatusNotFound, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*productcatalog.FeatureInvalidFiltersError](ctx, http.StatusBadRequest, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*productcatalog.FeatureInvalidMeterAggregationError](ctx, http.StatusBadRequest, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*models.MeterNotFoundError](ctx, http.StatusNotFound, err, w) ||
commonhttp.HandleErrorIfTypeMatches[*productcatalog.FeatureWithNameAlreadyExistsError](ctx, http.StatusConflict, err, w)
}
}
11 changes: 11 additions & 0 deletions pkg/errorsx/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package errorsx

import "errors"

func ErrorAs[T error](err error) (T, bool) {
var outerr T
if errors.As(err, &outerr) {
return outerr, true
}
return outerr, false
}
19 changes: 19 additions & 0 deletions pkg/framework/commonhttp/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"net/http"

"github.com/openmeterio/openmeter/pkg/errorsx"
"github.com/openmeterio/openmeter/pkg/models"
)

Expand Down Expand Up @@ -50,3 +51,21 @@ func ErrorEncoder(ctx context.Context, _ error, w http.ResponseWriter) bool {

return false
}

// HandleErrorIfTypeMatches checks if the error is of the given type and encodes it as an HTTP error.
// Using the generic feature we can mandate that the error implements the error interface. This is a
// must, as the errors.As would panic if the error does not implement the error interface.
func HandleErrorIfTypeMatches[T error](ctx context.Context, statusCode int, err error, w http.ResponseWriter, extendedProblemFunc ...func(T) (string, string)) bool {
if err, ok := errorsx.ErrorAs[T](err); ok {
extendedProblemFuncs := make([]ExtendProblemFunc, 0, len(extendedProblemFunc))
for _, f := range extendedProblemFunc {
extendedProblemFuncs = append(extendedProblemFuncs, func() (string, string) {
return f(err)
})
}
NewHTTPError(statusCode, err, extendedProblemFuncs...).EncodeError(ctx, w)
return true
}

return false
}

0 comments on commit e11f4bc

Please sign in to comment.