将响应标头添加到每个处理程序,而不重复相同的行

时间:2016-04-08 01:49:31

标签: go handler

我正在编写一个小型网站,对于每个页面,我都在其标题中添加服务器名称:

func httpSignUp(rw http.ResponseWriter, req *http.Request) {
    rw.Header().Set("Server", SERVER_NAME)
}

我想知道是否有一种方法可以设置http.ResponseWriter的默认服务器名称,所以我不必一遍又一遍地使用同一行?

3 个答案:

答案 0 :(得分:9)

创建一个包装器来设置标题:

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))

答案 1 :(得分:3)

  

“首选合成继承” - Gang of 4

首先,Golang并没有设计为Golang。 ;)

如果您正在寻找关于 why 部分的详细解释,我相信这已在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)
  })
}

最后,您可以灵活地选择“继承”哪个处理程序:

http.Handle("/path", adapter(your_handler))

或者如果它意味着每个处理程序,只需“继承”到root-handler:

http.ListenAndServe(port, adapter(root_Handler))

答案 2 :(得分:3)

http.ResponseWriterinterface,而非struct。所以,你不能直接扩展它。您需要扩展内部struct。但这不是解决这个问题的惯用方法。

您可以采用的一种方法是使用middlewaremiddleware只是一段代码,它将在主请求处理程序之前执行,并可用于执行一些常见任务。

例如,使用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))
相关问题