Go 如果已经设置了头,如何使用自定义http处理程序/中间件?

Go 如果已经设置了头,如何使用自定义http处理程序/中间件?,go,http-headers,gorilla,Go,Http Headers,Gorilla,我试图在go中链接HTTP处理程序,以提供一些附加功能,如: package router import ( // snip "github.com/gorilla/mux" "github.com/gorilla/handlers" "net/http" ) // snip r := mux.NewRouter() /* routing code */ var h http.Handler h = r if useGzip { h = handle

我试图在go中链接HTTP处理程序,以提供一些附加功能,如:

package router

import (
    // snip
    "github.com/gorilla/mux"
    "github.com/gorilla/handlers"
    "net/http"
)

// snip

r := mux.NewRouter()
/* routing code */
var h http.Handler
h = r
if useGzip {
    h = handlers.CompressHandler(h)
}
if useLogFile {
    fn := pathToLog
    accessLog, err := os.OpenFile(fn, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
    if err != nil {
        panic(err)
    }
    h = handlers.CombinedLoggingHandler(accessLog, h)
}

// etc...
问题是,如果gorilla/mux路由器指向的某个控制器已经设置了任何HTTP头(例如,
w.WriteHeader(404)
w.Header().set(“内容类型”、“应用程序/json”)
),这会自动中断任何试图设置或添加自己头的“包装器”处理程序,如。我看不到任何错误,除非我忘了在某个地方捕获错误,但浏览器收到无效响应


除了将标题存放在某个地方,然后让最后一个处理程序编写它们之外,还有什么优雅的方法来处理这个问题吗?这似乎意味着要重写处理程序的代码,如果可能的话,我希望避免这样做

一旦你调用
w.WriteHeader(404)
,报头就会连接到电线上。所以你不能再增加了。 最好的方法是缓冲状态代码并将其写入链的末尾

例如,您可以为
http.ResponseWriter
提供自己的包装器,它将重新实现
WriteHeader()
以保存状态值。然后添加方法
Commit()
来实际编写它。
在最后一个处理程序中调用
Commit()
。当然,您必须以某种方式确定哪个处理程序是最后一个。

我也经历过同样的失败行为。但只有在处理程序中,我才编写Header来设置除StatusOK之外的状态代码。我认为CompressHandler的这部分出了问题:

if h.Get("Content-Type") == "" {
    h.Set("Content-Type", http.DetectContentType(b))
}
在我自己的处理程序中显式设置内容类型时,似乎可以解决此问题:

w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(code)