Golang HTTP 自定义错误处理响应
Golang HTTP custom error handling response
我正在经历 https://blog.golang.org/error-handling-and-go,最后它给出了一个很好的例子,说明如何以更简洁的方式处理返回的错误,并使事情变得简单:
// Wrapper for handler functions.
type rootHandler func(http.ResponseWriter, *http.Request) error
// Implement the http.Handler interface.
func (fn rootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
err := fn(w, r) // Call handler function.
if err == nil {
return
}
...
}
// POST /api/test/
testRouter.
Handle("/", rootHandler(create)).
Methods("POST")
// GET /api/test/{id}/
testRouter.
HandleFunc("/{id:[0-9]+}/", rootHandler(getByID)).
Methods("GET")
func create(w http.ResponseWriter, r *http.Request) error {
// CustomError implementes error
return &CustomError{
Kind: EPARSE,
Status: http.StatusBadRequest,
Message: "some message",
Op: "create",
Err: err,
}
}
这非常有效,但我不希望将每个控制器方法(在本例中为 create
)包装在 rootHandler
中,并且认为最好的方法是找出某种 post-中间件。我未能尝试创建路由器使用的 post-middlewhere 而不是每个控制器方法,并且想知道您将如何实现它。我能找到的关于 SO 的最接近的答案是 emmbee 在 上的答案,除了 AuthMiddleware 中的 fn 将是一个控制器方法。
所以理想情况下,我会有下面的处理程序来处理 CustomError
如果它存在
// POST /api/test
testRouter.
Handle("/", create).
Methods("POST")
对于上下文,我使用的是 gorilla mux 和 negroni。
如有任何想法,我们将不胜感激!非常感谢。
您的理想解决方案行不通。 mux API 支持 http.Handler
和 func(http.ResponseWriter, *http.Request)
参数。你有一个func(http.ResponseWriter, *http.Request) error
。 func(http.ResponseWriter, *http.Request) error
不能作为 mux API.
支持的参数类型之一传递
唯一的解决方案是使用 rootHandler
wrapper 使每个控制器功能适应多路复用器 API 支持的类型。与标准 http.HandlerFunc
包装器相比,包装器不会增加开销。
使用辅助函数减少包装器所需的代码量:
func handle(r *mux.Router, p string, fn func(http.ResponseWriter, *http.Request) error) *mux.Route {
return r.Handle(path, rootHandler(fn))
}
...
handle(testRouter, "/", create).Methods("POST")
handle(testRouter, "/{id:[0-9]+}/", getByID).Methods("GET")
在辅助函数中使用类型开关来处理不同的控制器类型:
func handle(r *mux.Router, p string, h interface{}) *mux.Route {
switch h := h.(type) {
case func(http.ResponseWriter, *http.Request) error:
return r.Handle(p, rootHandler(h))
case func(http.ResponseWriter, *http.Request):
return r.HandleFunc(p, h)
case http.Handler:
return r.Handle(p, h)
default:
panic(fmt.Sprintf("handler type %T not supported", h))
}
}
我正在经历 https://blog.golang.org/error-handling-and-go,最后它给出了一个很好的例子,说明如何以更简洁的方式处理返回的错误,并使事情变得简单:
// Wrapper for handler functions.
type rootHandler func(http.ResponseWriter, *http.Request) error
// Implement the http.Handler interface.
func (fn rootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
err := fn(w, r) // Call handler function.
if err == nil {
return
}
...
}
// POST /api/test/
testRouter.
Handle("/", rootHandler(create)).
Methods("POST")
// GET /api/test/{id}/
testRouter.
HandleFunc("/{id:[0-9]+}/", rootHandler(getByID)).
Methods("GET")
func create(w http.ResponseWriter, r *http.Request) error {
// CustomError implementes error
return &CustomError{
Kind: EPARSE,
Status: http.StatusBadRequest,
Message: "some message",
Op: "create",
Err: err,
}
}
这非常有效,但我不希望将每个控制器方法(在本例中为 create
)包装在 rootHandler
中,并且认为最好的方法是找出某种 post-中间件。我未能尝试创建路由器使用的 post-middlewhere 而不是每个控制器方法,并且想知道您将如何实现它。我能找到的关于 SO 的最接近的答案是 emmbee 在
所以理想情况下,我会有下面的处理程序来处理 CustomError
如果它存在
// POST /api/test
testRouter.
Handle("/", create).
Methods("POST")
对于上下文,我使用的是 gorilla mux 和 negroni。
如有任何想法,我们将不胜感激!非常感谢。
您的理想解决方案行不通。 mux API 支持 http.Handler
和 func(http.ResponseWriter, *http.Request)
参数。你有一个func(http.ResponseWriter, *http.Request) error
。 func(http.ResponseWriter, *http.Request) error
不能作为 mux API.
唯一的解决方案是使用 rootHandler
wrapper 使每个控制器功能适应多路复用器 API 支持的类型。与标准 http.HandlerFunc
包装器相比,包装器不会增加开销。
使用辅助函数减少包装器所需的代码量:
func handle(r *mux.Router, p string, fn func(http.ResponseWriter, *http.Request) error) *mux.Route {
return r.Handle(path, rootHandler(fn))
}
...
handle(testRouter, "/", create).Methods("POST")
handle(testRouter, "/{id:[0-9]+}/", getByID).Methods("GET")
在辅助函数中使用类型开关来处理不同的控制器类型:
func handle(r *mux.Router, p string, h interface{}) *mux.Route {
switch h := h.(type) {
case func(http.ResponseWriter, *http.Request) error:
return r.Handle(p, rootHandler(h))
case func(http.ResponseWriter, *http.Request):
return r.HandleFunc(p, h)
case http.Handler:
return r.Handle(p, h)
default:
panic(fmt.Sprintf("handler type %T not supported", h))
}
}