在大猩猩中,使用RecoveryHandler我们可以抑制恐慌。但是有一个处理程序或库方法来响应特定的Http状态代码和给定错误类型的消息
例如,如果发生Mandatory field missing error
恐慌,可能需要回复Http 400
以及有效负载确切错误的有意义消息。
建议的方法是什么?
的更新
在代码中:列出了2种方法
func fooHandler(w http.ResponseWriter, r *http.Request) {
//decode the request body into a struct instance
if err := decode(r, myInstance); err != nil {
sendErrorResponse(w,err,http.StatusBadRequest)
return
}
//validate the struct instance for all mandatory keys presence
if err := file.validate(); err != nil {
sendErrorResponse(w,err,http.StatusBadRequest)
return
}
//call DB and validate the response and handle the error
//do some computation and again handle error.
//finally construct response
}
func barHandler(w http.ResponseWriter, r *http.Request) {
//similar to above handler many funcs are called before the response is contruscted
}
func tomHandler(w http.ResponseWriter, r *http.Request) {
//similar to above handler many funcs are called before the response is contruscted
}
func differentHandler(w http.ResponseWriter, r *http.Request) {
defer recoverForErrors(w,r)
// call as many funcs as you need.
// validation, decoding etc will panic instead of returning errors.
// This will avoid the repetitive boiler plate code of handling error and converting to meaningful error response
// instead all this logic is pushed to recoverForErrors func. Which retrieves the error from panic and checks for
// specific error type to construct the error http response
}
答案 0 :(得分:4)
尽可能依靠标准库提供的接口是惯用的。在这种情况下,来自net/http包的http.Handler
接口。
在您的情况下,您可以创建一个新类型,允许处理程序返回错误类型,并集中处理所有这些错误情况。
// StatusError wraps an existing error with a HTTP status code.
type StatusError struct {
Status int
// Allows you to wrap another error
Err error
}
func (e *StatusError) Error() string {
return e.Error()
}
type AppHandler func(w http.ResponseWriter, r *http.Request) error
// Satisfies the http.Handler interface
func (ah AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Centralises your error handling
err := ah(w, r)
if err != nil {
switch e := a.(type) {
case *StatusError:
switch e.Status {
case 400:
http.Error(w, e.Err.Error(), 400)
return
case 404:
http.NotFound(w, r)
return
default:
http.Error(w, http.StatusText(500), 500)
return
}
default:
http.Error(w, http.StatusText(500), 500)
return
}
}
// Your handlers will look like this
func SomeHandler(w http.ResponseWriter, r *http.Request) error {
err := decode(r, myInstance)
if err != nil {
return &StatusError{400, err}
}
err := file.validate()
if err != nil {
return &StatusError{400, err}
}
// Continue on...
return nil
}
您在这里获得的好处包括:
ServeHTTP
方法中集中处理错误 - 例如,对于400错误,您可以将错误原因写入响应。对于500个错误,您可能会返回一般消息,因为HTTP 500不是用户可以解决的问题。return
语句来避免继续执行。StatusError
类型使用状态代码包装错误,但仍允许您轻松检查/记录/写出包装错误。进一步阅读: