wI2L / fizz

:lemon: Gin wrapper with OpenAPI 3 spec generation
https://pkg.go.dev/github.com/wI2L/fizz
MIT License
214 stars 52 forks source link

Specify Multiple error responses? #40

Closed hmajid2301 closed 4 years ago

hmajid2301 commented 4 years ago

How can I specify multiple error responses, say I have the following code:

func routes(grp *fizz.RouterGroup) {
    grp.POST("", []fizz.OperationOption{
        fizz.Summary("Create a new game type."),
        fizz.Response(fmt.Sprint(http.StatusBadRequest), "Bad request", nil, nil),
        fizz.Response(fmt.Sprint(http.StatusConflict), "Does not exist", nil, nil),
    }, tonic.Handler(controllers.CreateGameType, http.StatusOK))
}

How can I specify within my CreateGameType to either return a 400 error or a 409 error. Any error I return (such as using juju as shown in the example, errors.AlreadyExistsf("conflict"), always returns a 400 error.

func CreateGameType(c *gin.Context, game *models.NewGame) (struct{}, error) {
    ....
}

Thanks

wI2L commented 4 years ago

@hmajid2301 Hello, You can lookup the error type and return the adequate status code using a middleware, like so:

// errHook is the error hook registered with Tonic
// that interprets the handlers errors.
func errHook(c *gin.Context, e error) (int, interface{}) {
    code, msg := 500, http.StatusText(http.StatusInternalServerError)

    if _, ok := e.(tonic.BindError); ok {
        code, msg = 400, e.Error()
    } else {
        switch {
        case errors.IsBadRequest(e), errors.IsNotValid(e), errors.IsNotSupported(e), errors.IsNotAssigned(e), errors.IsNotProvisioned(e):
            code, msg = 400, e.Error()
        case errors.IsForbidden(e):
            code, msg = 403, e.Error()
        case errors.IsMethodNotAllowed(e):
            code, msg = 405, e.Error()
        case errors.IsNotFound(e), errors.IsUserNotFound(e):
            code, msg = 404, e.Error()
        case errors.IsUnauthorized(e):
            code, msg = 401, e.Error()
        case errors.IsAlreadyExists(e):
            code, msg = 409, e.Error()
        case errors.IsNotImplemented(e):
            code, msg = 501, e.Error()
        }
    }
    return code, gin.H{`error`: msg}
}

Register this using the tonic.SetErrorHook(errHook) method.