gpt4 book ai didi

http - 从外部 Go 中间件控制 HTTP header

转载 作者:行者123 更新时间:2023-12-02 01:51:14 25 4
gpt4 key购买 nike

假设我在 Go 中有一个中间件,我想用我自己的值覆盖任何现有的 Server header 。

// Server attaches a Server header to the response.
func Server(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("/", authHandler)
http.ListenAndServe(":8000", Server(http.DefaultServeMux, "myapp"))

不幸的是,如果 authHandler 或 DefaultServeMux 处理的任何内容调用 w.Header().Add("Server", "foo") (例如 httputil.ReverseProxy.ServeHTTP ),我最终会响应中有两个服务器 header 。

$ http localhost:5962/v1/hello_world
HTTP/1.1 200 OK
Content-Length: 11
Content-Type: text/plain
Date: Tue, 12 Jul 2016 04:54:04 GMT
Server: inner-middleware
Server: myapp

我真正想要的是这样的:

// Server attaches a Server header to the response.
func Server(h http.Handler, serverName string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
w.Header().Set("Server", serverName)
})
}

但是,这是disallowed by the semantics of ServeHTTP :

ServeHTTP should write reply headers and data to the ResponseWriter and then return. Returning signals that the request is finished; it is not valid to use the ResponseWriter or read from the Request.Body after or concurrently with the completion of the ServeHTTP call.

我见过一些相当丑陋的黑客攻击,例如 httputil.ReverseProxy.ServeHTTP 中的代码,它复制 header 并重写响应代码,或使用 httptest.ResponseRecorder,它将整个正文读取到字节缓冲区中。

我还可以颠倒传统的中间件顺序,以某种方式将我的服务器中间件放在最后,或者使其成为最里面的中间件。

我缺少什么简单的方法吗?

最佳答案

您可以定义一个自定义类型,它包装 ResponseWriter 并在写入所有 header 之前插入服务器 header ,但需要额外的间接层。这是一个例子:

type serverWriter struct {
w http.ResponseWriter
name string
wroteHeader bool
}

func (s serverWriter) WriteHeader(code int) {
if s.wroteHeader == false {
s.w.Header().Set("Server", s.name)
s.wroteHeader = true
}
s.w.WriteHeader(code)
}

func (s serverWriter) Write(b []byte) (int, error) {
return s.w.Write(b)
}

func (s serverWriter) Header() http.Header {
return s.w.Header()
}

// Server attaches a Server header to the response.
func Server(h http.Handler, serverName string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
sw := serverWriter{
w: w,
name: serverName,
wroteHeader: false,
}
h.ServeHTTP(sw, r)
})
}

我在这里写了更多相关内容。 https://kev.inburke.com/kevin/how-to-write-go-middleware/

关于http - 从外部 Go 中间件控制 HTTP header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58776775/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com