首页 文章

在go中为多个处理程序设置http标头

提问于
浏览
4

我正在尝试为多个处理程序设置http标头 . 我的第一个想法是创建一个自定义写入函数,在写入响应之前设置 Headers ,就像底部的代码示例一样 .

但是,当我将指针传递给http.ResponseWriter并尝试从我的函数访问它时,它告诉我“type * http.ResponseWriter没有Header方法” .

为多个处理程序设置标头的最佳方法是什么,以及为什么指针不按我想要的方式工作?

func HelloServer(w http.ResponseWriter, req *http.Request) {
    type Message struct {
        Name string
        Body string
        Time int64
    }

    m := Message{"Alice", "Hello", 1294706395881547000}

    b, _ := json.Marshal(m)
    WriteJSON(&w, b)
}

func WriteJSON(wr *http.ResponseWriter, rawJSON []byte) {
    *wr.Header().Set("Content-Type", "application/json")

    io.WriteString(*wr, string(rawJSON))
}

func main() {
    http.HandleFunc("/json", HelloServer)

    err := http.ListenAndServe(":9000", nil)
    if err != nil {
    log.Fatal("ListenAndServer: ", err)
    }
}

4 回答

  • 0

    我不确定多处理程序的事情,但我知道为什么你写的代码失败了 . 关键是该行:

    *wr.Header().Set("Content-Type", "application/json")
    

    由于运算符优先级,正被解释为:

    *(wr.Header().Set("Content-Type", "application/json"))
    

    由于 wr 的类型为 *http.ResponseWriter ,它是指向和接口的指针,而不是接口本身,因此不起作用 . 我假设你知道,这就是为什么你做了 *wr . 我假设你对编译器意味着什么:

    (*wr).Header().Set("Content-Type", "application/json")
    

    如果我没有弄错的话,那应该编译并且行为正常 .

  • 0

    您不需要使用 *wr ,因为它已经引用了指针 .

    wr.Header().Set("Content-Type", "application/json") 应该足够了 .

    如果要为每个请求设置"global"标头,可以创建一个满足 http.HandleFuncgo.auth has a good example)的函数,然后像这样包装处理程序:

    http.HandleFunc("/hello", Defaults(helloHandler))

    另请查看 net/http 文档,which has further examples .

  • 1

    我用一个调用我的AddSafeHeader函数的错误处理程序包装我的处理程序 .

    我基于http://golang.org/doc/articles/error_handling.html但它不使用ServeHTTP所以它适用于appstats:

    http.Handle("/", appstats.NewHandler(util.ErrorHandler(rootHandler)))
    

    这里:

    package httputil
    
    import (
      "appengine"
      "net/http"
      "html/template"
    )
    
    func AddSafeHeaders(w http.ResponseWriter) {
      w.Header().Set("X-Content-Type-Options", "nosniff")
      w.Header().Set("X-XSS-Protection", "1; mode=block")
      w.Header().Set("X-Frame-Options", "SAMEORIGIN")
      w.Header().Set("Strict-Transport-Security", "max-age=2592000; includeSubDomains")
    }
    
    // Redirect to a fixed URL
    type redirectHandler struct {
      url  string
      code int
    }
    
    func (rh *redirectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
      Redirect(w, r, rh.url, rh.code)
    }
    
    func Redirect(w http.ResponseWriter, r *http.Request, urlStr string, code int) {
      AddSafeHeaders(w)
      http.Redirect(w, r, urlStr, code)
    }
    
    // RedirectHandler returns a request handler that redirects
    // each request it receives to the given url using the given
    // status code.
    func RedirectHandler(url string, code int) http.Handler {
      return &redirectHandler{url, code}
    }
    
    func ErrorHandler(fn func(appengine.Context, http.ResponseWriter, *http.Request)) func(appengine.Context, http.ResponseWriter, *http.Request) {
      return func(c appengine.Context, w http.ResponseWriter, r *http.Request) {
        defer func() {
          if err, ok := recover().(error); ok {
            c.Errorf("%v", err)
            w.WriteHeader(http.StatusInternalServerError)
            errorTemplate.Execute(w, err)
          }
        }()
        AddSafeHeaders(w)
        fn(c, w, r)
      }
    }
    
    // Check aborts the current execution if err is non-nil.
    func Check(err error) {
      if err != nil {
        panic(err)
      }
    }
    
    var errorTemplate = template.Must(template.New("error").Parse(errorTemplateHTML))
    
    const errorTemplateHTML = `
    <html>
    <head>
            <title>XXX</title>
    </head>
    <body>
            <h2>An error occurred:</h2>
            <p>{{.}}</p>
    </body>
    </html>
    `
    
  • 4

    http.ResponseWriter是一个界面 .

    您可能不应该使用指向接口的指针 . 在net / http / server.go中,未导出的 response 结构是服务器调用处理程序时实现 ResponseWriter 的实际类型,重要的是when the server actually calls the handler's ServeHTTP,它传递 *response . 它已经是一个指针,但你没有看到,因为 ResonseWriter 是一个接口 . (响应指针由here创建here . (链接可能是未来的错误行,但您应该能够找到它们) .

    这就是实现 Handler 所需的 ServeHTTP 函数的原因:

    ServeHTTP(w ResponseWriter, r *Request)
    

    即不是指向 ResponseWriter 的指针,因为此声明已经允许指向实现 ResponseWriter 接口的结构的指针 .

相关问题