Golang中如何向http.TimeoutHandler传递自定义头部
Golang中如何向http.TimeoutHandler传递自定义头部
目前无法覆盖 http.TimeoutHandler 的内容类型(Content-Type)标头,因此无法渲染 JSON 消息,也无法将 Content-Type 标头设置为 JSON。是否有办法解决这个问题?
这个问题在这里也被提及过,但被忽略了。
响应始终是文本内容类型。
func TimeoutHandler(timeout time.Duration) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.TimeoutHandler(next, timeout, `{"key":"value"}`)
}
}
更多关于Golang中如何向http.TimeoutHandler传递自定义头部的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中如何向http.TimeoutHandler传递自定义头部的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在 http.TimeoutHandler 中设置自定义头部确实需要特殊处理,因为超时响应会绕过原始处理程序。以下是解决方案:
type timeoutWriter struct {
http.ResponseWriter
headersWritten bool
}
func (tw *timeoutWriter) WriteHeader(status int) {
if !tw.headersWritten {
tw.headersWritten = true
tw.ResponseWriter.Header().Set("Content-Type", "application/json")
}
tw.ResponseWriter.WriteHeader(status)
}
func (tw *timeoutWriter) Write(b []byte) (int, error) {
if !tw.headersWritten {
tw.headersWritten = true
tw.ResponseWriter.Header().Set("Content-Type", "application/json")
}
return tw.ResponseWriter.Write(b)
}
func TimeoutHandler(timeout time.Duration) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tw := &timeoutWriter{ResponseWriter: w}
handler := http.TimeoutHandler(next, timeout, `{"error":"request timeout"}`)
handler.ServeHTTP(tw, r)
})
}
}
或者使用更简洁的包装器方法:
func JSONTimeoutHandler(h http.Handler, timeout time.Duration) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
timeoutHandler := http.TimeoutHandler(h, timeout, `{"error":"request timeout"}`)
timeoutHandler.ServeHTTP(w, r)
})
}
// 使用示例
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
time.Sleep(2 * time.Second) // 模拟耗时操作
w.Write([]byte(`{"status":"ok"}`))
})
handler := JSONTimeoutHandler(mux, 1*time.Second)
http.ListenAndServe(":8080", handler)
}
对于更复杂的场景,可以创建自定义超时处理器:
type jsonTimeoutHandler struct {
handler http.Handler
timeout time.Duration
body string
}
func (h *jsonTimeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
done := make(chan struct{})
go func() {
h.handler.ServeHTTP(w, r)
close(done)
}()
select {
case <-done:
return
case <-time.After(h.timeout):
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(h.body))
}
}
func NewJSONTimeoutHandler(handler http.Handler, timeout time.Duration, timeoutBody string) http.Handler {
return &jsonTimeoutHandler{
handler: handler,
timeout: timeout,
body: timeoutBody,
}
}
这些方法确保超时响应始终返回正确的 JSON Content-Type 头部。

