使用 Negroni 时自定义 HTTP 处理程序可以全局使用还是仅按请求使用?
Can a custom HTTP handler be used globally when using Negroni or only per request?
为了确保错误结果在所有请求中得到正确处理,我正在实施自定义处理程序,如 http://blog.golang.org/error-handling-and-go 中所述。因此,处理程序不是只接受 w http.ResponseWriter, r *http.Request
参数,而是可选地 returns 和 error
.
我正在使用 Negroni,我想知道我是否可以设置一次将所有请求包装到 handler
中,或者是否总是必须像 [=] 那样根据每个请求进行设置下例中的 14=] 和 /foo
?
type handler func(w http.ResponseWriter, r *http.Request) error
// ServeHTTP checks for error results and handles them globally
func (fn handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
http.Error(w, err, http.StatusInternalServerError)
}
}
// Index matches the `handler` type and returns an error
func Index(w http.ResponseWriter, r *http.Request) error {
return errors.New("something went wrong")
}
func main() {
router := mux.NewRouter()
// note how `Index` is wrapped into `handler`. Is there a way to
// make this global? Or will the handler(fn) pattern be required
// for every request?
router.Handle("/", handler(Index)).Methods("GET")
router.Handle("/foo", handler(Index)).Methods("GET")
n := negroni.New(
negroni.NewRecovery(),
negroni.NewLogger(),
negroni.Wrap(router),
)
port := os.Getenv("PORT")
n.Run(":" + port)
}
如果需要,您可以围绕 r.Handle
编写一个包装器。您不能使用 Negroni 全局执行此操作,因为并非您使用的所有中间件都假定您的 handler
类型。
例如
// Named to make the example clear.
func wrap(r *mux.Router, pattern string, h handler) *mux.Route {
return r.Handle(pattern, h)
}
func index(w http.ResponseWriter, r *http.Request) error {
io.WriteString(w, "Hello")
return nil
}
func main() {
r := mux.NewRouter()
wrap(r, "/", index)
http.ListenAndServe(":8000", r)
}
我认为这并不比直接对您的处理程序进行类型转换(这很清楚,如果有点重复)或将您的处理程序类型转换为结构好不了多少。后者您稍后可以扩展以包含线程安全字段(您的数据库池、应用程序配置等),然后您可以显式地将它们与每个处理程序一起传递。
实际上,您当前的路由器代码仍然清晰易读,并且(对其他人)很明显是什么类型支持您的处理程序。
为了确保错误结果在所有请求中得到正确处理,我正在实施自定义处理程序,如 http://blog.golang.org/error-handling-and-go 中所述。因此,处理程序不是只接受 w http.ResponseWriter, r *http.Request
参数,而是可选地 returns 和 error
.
我正在使用 Negroni,我想知道我是否可以设置一次将所有请求包装到 handler
中,或者是否总是必须像 [=] 那样根据每个请求进行设置下例中的 14=] 和 /foo
?
type handler func(w http.ResponseWriter, r *http.Request) error
// ServeHTTP checks for error results and handles them globally
func (fn handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := fn(w, r); err != nil {
http.Error(w, err, http.StatusInternalServerError)
}
}
// Index matches the `handler` type and returns an error
func Index(w http.ResponseWriter, r *http.Request) error {
return errors.New("something went wrong")
}
func main() {
router := mux.NewRouter()
// note how `Index` is wrapped into `handler`. Is there a way to
// make this global? Or will the handler(fn) pattern be required
// for every request?
router.Handle("/", handler(Index)).Methods("GET")
router.Handle("/foo", handler(Index)).Methods("GET")
n := negroni.New(
negroni.NewRecovery(),
negroni.NewLogger(),
negroni.Wrap(router),
)
port := os.Getenv("PORT")
n.Run(":" + port)
}
如果需要,您可以围绕 r.Handle
编写一个包装器。您不能使用 Negroni 全局执行此操作,因为并非您使用的所有中间件都假定您的 handler
类型。
例如
// Named to make the example clear.
func wrap(r *mux.Router, pattern string, h handler) *mux.Route {
return r.Handle(pattern, h)
}
func index(w http.ResponseWriter, r *http.Request) error {
io.WriteString(w, "Hello")
return nil
}
func main() {
r := mux.NewRouter()
wrap(r, "/", index)
http.ListenAndServe(":8000", r)
}
我认为这并不比直接对您的处理程序进行类型转换(这很清楚,如果有点重复)或将您的处理程序类型转换为结构好不了多少。后者您稍后可以扩展以包含线程安全字段(您的数据库池、应用程序配置等),然后您可以显式地将它们与每个处理程序一起传递。
实际上,您当前的路由器代码仍然清晰易读,并且(对其他人)很明显是什么类型支持您的处理程序。