在不重复同一行的情况下向每个处理程序添加响应 header
Add response header to every handler without repeating the same line
我正在写一个小网站,对于每个页面,我都在其 header:
中添加了一个服务器名称
func httpSignUp(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("Server", SERVER_NAME)
}
我想知道是否有一种方法可以设置 http.ResponseWriter 的默认服务器名称,这样我就不必一遍又一遍地使用同一行?
创建包装器以设置 header:
func wrap(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (
w.Header().Set("Server", SERVER_NAME)
h.ServeHTTP(w, r)
})
}
包装单个处理程序
http.Handle("/path", wrap(aHandler)(
http.Handle("/another/path", wrap(anotherHandler))
或传递给 ListenAndServe 的根处理程序:
log.Fatal(http.ListenAndServe(addr, wrap(rootHandler))
"Prefer composition to inheritance" - Gang of 4
继承一开始就没有设计到 Golang 中。 ;)
如果您正在寻找关于 为什么 部分的详细解释,我相信这已经在 SO 上得到了回答,因此我会指出它:Embedding instead of inheritance in Go .
好吧,您实际上可以使用 适配器设计模式 实现相同的结果,它使您能够从内置库扩展功能,对我来说,它的方式更灵活比继承。
func adapter(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", SERVER_NAME)
h.ServeHTTP(w, r)
})
}
或者传入serverName
作为参数:
func adapter(h http.Handler, serverName string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", serverName)
h.ServeHTTP(w, r)
})
}
最后,您可以灵活地选择处理程序 'inherited':
http.Handle("/path", adapter(your_handler))
或者如果它意味着每个处理程序,只需 'inherit' 到根处理程序:
http.ListenAndServe(port, adapter(root_Handler))
http.ResponseWriter
是 interface
,而不是 struct
。所以,你不能直接扩展它。您需要扩展内部 struct
。但这不是解决这个问题的惯用方法。
您可以采用的一种方法是使用 middleware
。 middleware
只是一段代码,将在您的主请求处理程序之前执行,可用于执行一些常见任务。
例如,使用middleware
方法写同样的东西:
func injectServerHeader(handler http.Handler, serverName string) http.Handler {
ourFunc := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", serverName)
handler.ServeHTTP(w, r)
}
return http.HandlerFunc(ourFunc)
}
这样,您就用中间件包装了实际的 http 处理程序。因此,您不必一遍又一遍地编写相同的代码。
例如:
http.Handle("/some-path", injectServerHeader(aHandler))
我正在写一个小网站,对于每个页面,我都在其 header:
中添加了一个服务器名称func httpSignUp(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("Server", SERVER_NAME)
}
我想知道是否有一种方法可以设置 http.ResponseWriter 的默认服务器名称,这样我就不必一遍又一遍地使用同一行?
创建包装器以设置 header:
func wrap(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (
w.Header().Set("Server", SERVER_NAME)
h.ServeHTTP(w, r)
})
}
包装单个处理程序
http.Handle("/path", wrap(aHandler)(
http.Handle("/another/path", wrap(anotherHandler))
或传递给 ListenAndServe 的根处理程序:
log.Fatal(http.ListenAndServe(addr, wrap(rootHandler))
"Prefer composition to inheritance" - Gang of 4
继承一开始就没有设计到 Golang 中。 ;)
如果您正在寻找关于 为什么 部分的详细解释,我相信这已经在 SO 上得到了回答,因此我会指出它:Embedding instead of inheritance in Go .
好吧,您实际上可以使用 适配器设计模式 实现相同的结果,它使您能够从内置库扩展功能,对我来说,它的方式更灵活比继承。
func adapter(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", SERVER_NAME)
h.ServeHTTP(w, r)
})
}
或者传入serverName
作为参数:
func adapter(h http.Handler, serverName string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", serverName)
h.ServeHTTP(w, r)
})
}
最后,您可以灵活地选择处理程序 'inherited':
http.Handle("/path", adapter(your_handler))
或者如果它意味着每个处理程序,只需 'inherit' 到根处理程序:
http.ListenAndServe(port, adapter(root_Handler))
http.ResponseWriter
是 interface
,而不是 struct
。所以,你不能直接扩展它。您需要扩展内部 struct
。但这不是解决这个问题的惯用方法。
您可以采用的一种方法是使用 middleware
。 middleware
只是一段代码,将在您的主请求处理程序之前执行,可用于执行一些常见任务。
例如,使用middleware
方法写同样的东西:
func injectServerHeader(handler http.Handler, serverName string) http.Handler {
ourFunc := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", serverName)
handler.ServeHTTP(w, r)
}
return http.HandlerFunc(ourFunc)
}
这样,您就用中间件包装了实际的 http 处理程序。因此,您不必一遍又一遍地编写相同的代码。
例如:
http.Handle("/some-path", injectServerHeader(aHandler))