我正在尝试使用 go-chi 开发一个 api 网关。我希望如果请求在查询中包含“_always200=true”,我会将状态代码设置为 200。 这是我尝试过的: custom_response_writer.go:
type CustomResponseWriter struct { http.ResponseWriter Buf *bytes.Buffer StatusCode int WroteHeader bool } func NewCustomResponseWriter(w http.ResponseWriter) *CustomResponseWriter { return &CustomResponseWriter{ResponseWriter: w, Buf: new(bytes.Buffer)} } func (c *CustomResponseWriter) WriteHeader(code int) { c.StatusCode = code c.ResponseWriter.WriteHeader(code) } func (c *CustomResponseWriter) Write(b []byte) (int, error) { return c.Buf.Write(b) }
中间件:
func HeaderFilterMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { always200, _ := r.Context().Value(always200QueryKey).(bool) crw := NewCustomResponseWriter(w) next.ServeHTTP(crw, r) if always200 { crw.WriteHeader(http.StatusOK) } }) }
总是返回404。有什么办法可以解决这个问题吗?
代码中至少存在两个问题。
always200, _ := r.Context().Value(always200QueryKey).(bool)
不是获取查询参数的正确方法。我认为您应该使用 r.URL.Query().Get("_always200")
来读取它,并将该值与字符串 "true"
进行比较。
在 next.ServeHTTP(crw, r)
之后调用 crw.WriteHeader(http.StatusOK)
已经太晚了。当我测试代码时,它打印了此警告消息:
http: superfluous response.WriteHeader call from main.(*CustomResponseWriter).WriteHeader
以下是更改响应状态代码的修改示例:
package main
import (
"bytes"
"net/http"
"strings"
"github.com/go-chi/chi/v5"
)
type CustomResponseWriter struct {
http.ResponseWriter
Buf *bytes.Buffer
OriginalStatusCode int
WroteHeader bool
always200 bool
}
func NewCustomResponseWriter(w http.ResponseWriter, always200 bool) *CustomResponseWriter {
return &CustomResponseWriter{
ResponseWriter: w,
Buf: new(bytes.Buffer),
always200: always200,
}
}
func (c *CustomResponseWriter) WriteHeader(code int) {
c.OriginalStatusCode = code
if c.always200 {
code = http.StatusOK
}
c.ResponseWriter.WriteHeader(code)
}
func (c *CustomResponseWriter) Write(b []byte) (int, error) {
return c.Buf.Write(b)
}
func HeaderFilterMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
always200 := r.URL.Query().Get("_always200")
crw := NewCustomResponseWriter(w, strings.EqualFold(always200, "true"))
next.ServeHTTP(crw, r)
})
}
func main() {
r := chi.NewRouter()
r.Use(HeaderFilterMiddleware)
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("welcome"))
})
http.ListenAndServe(":3000", r)
}