我想获取每个路由上的所有http错误,而不是每次重写if 400,然后if 404,然后if 500,然后等等......所以我在每个路由处理程序中有一个ErrorHandler()
函数:
func (h *Handler) List(c *gin.Context) {
movies, err := h.service.ListService()
if err != nil {
utils.ErrorHandler(c, err)
return
}
c.JSON(http.StatusOK, movies)
}
这个函数看起来像这样:
func ErrorHandler(c *gin.Context, err error) {
if err == ErrNotFound {
// 404
c.JSON(http.StatusNotFound, gin.H{"error": ErrNotFound.Error()})
} else if err == ErrInternalServerError {
// 500
c.JSON(http.StatusInternalServerError, gin.H{"error": ErrInternalServerError.Error()})
} // etc...
}
ErrNotFound
或ErrInternalServerError
只是全局变量,初始化如下:
var ErrNotFound = errors.New(http.StatusText(http.StatusNotFound)) // 404
我想知道我做的是否正确,或者是否有更好的方法来做到这一点,比如在中间件内部捕获错误并直接返回响应?
使用node.js,我可以在中间件参数中发送err
,并像这样使用它:
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
if (err instanceof HttpError) {
res.status(err.status).json({error: err.message});
} else if (err instanceof Error) {
res.status(500).json({error: err.message});
} else {
res.status(500).send("Internal Server Error");
}
});
有类似的东西吗?
2条答案
按热度按时间fnx2tebb1#
使用中间件比使用函数(
utils
作为包名也不受欢迎)更习惯:值得注意的是,您在中间件func**内部调用
c.Next()
,然后才调用实际的错误处理代码,因此您要确保在调用了处理程序链的其余部分之后才进行错误处理。Next应该只在中间件内部使用。它在调用处理程序内部执行链中的挂起处理程序。[...]
使用中间件的好处是,你也可以传递参数给它,例如一个logger,你可能想稍后使用它作为错误处理的一部分,once,而不是每次直接调用
utils.ErrorHandler
时都传递它。在这个例子中,它看起来像这样(我使用Uber Zap loggers):然后处理程序将中止链,而不是调用函数,这样看起来更干净,也更容易维护:
需要注意的是,如果你在
c.AbortWithStatus
或c.AbortWithError
中设置了一个HTTP状态,你可能希望不要在错误处理程序中覆盖它,在这种情况下,你可以使用-1
作为状态代码来调用c.JSON()
:最后,使用中间件允许您在处理程序中多次调用
c.Error
,例如,当发生一系列非致命错误,并且您希望在实际中止请求之前捕获所有错误时。Error将一个错误附加到当前上下文。该错误将被推送到错误列表中。最好为解析请求过程中发生的每个错误调用Error。可以使用中间件来收集所有错误并[处理它们]
至于中间件中的实际错误处理,它非常简单,只需记住,所有对
c.Error
、c.AbortWith...
的调用都会将您的错误 Package 在gin.Error
中,因此要检查原始值,您必须检查err.Err
字段:在
c.Errors
上迭代可能看起来有些笨拙,因为现在您可能有N个错误而不是一个,但是根据您打算如何使用中间件,您可以简单地检查len(c.Errors) > 0
并只访问第一项c.Errors[0]
。rjjhvcjd2#
在中间件中处理错误的好处是集中处理错误,而不是在每个处理程序中显式处理异常。
为了减少响应Map错误,提出了一种相关的错误处理中间件gin-error。
使用示例: