使用中间件实现Golang net/http ServeMux的自定义错误响应
使用中间件实现Golang net/http ServeMux的自定义错误响应 我正在尝试在使用 net/http 的 ServeMux 时,为“未找到”和“方法不允许”的响应返回 JSON 格式的响应。我通过中间件实现了这个功能,并希望得到关于如何改进的反馈。另外,如果有更简单的方法,也请告诉我。谢谢!
type ResponseWriterInterceptor struct {
w http.ResponseWriter
status int
}
func (i *ResponseWriterInterceptor) Header() http.Header {
return i.w.Header()
}
func (i *ResponseWriterInterceptor) Write(b []byte) (int, error) {
if string(b) == "Method Not Allowed\n" || string(b) == "404 page not found\n" {
return 0, nil
}
return i.w.Write(b)
}
func (i *ResponseWriterInterceptor) WriteHeader(statusCode int) {
i.status = statusCode
}
func (app *application) JSONError(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
i := &ResponseWriterInterceptor{w: w}
next.ServeHTTP(i, r)
switch i.status {
case http.StatusNotFound:
app.notFoundResponse(w, r)
case http.StatusMethodNotAllowed:
app.methodNotAllowedResponse(w, r)
}
})
}
更多关于使用中间件实现Golang net/http ServeMux的自定义错误响应的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于使用中间件实现Golang net/http ServeMux的自定义错误响应的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你的中间件实现思路正确,但存在几个关键问题需要改进。以下是优化后的版本:
type ResponseWriterInterceptor struct {
http.ResponseWriter
status int
body []byte
}
func (i *ResponseWriterInterceptor) WriteHeader(statusCode int) {
i.status = statusCode
i.ResponseWriter.WriteHeader(statusCode)
}
func (i *ResponseWriterInterceptor) Write(b []byte) (int, error) {
if i.status == http.StatusNotFound || i.status == http.StatusMethodNotAllowed {
i.body = b
return len(b), nil
}
return i.ResponseWriter.Write(b)
}
func (app *application) JSONError(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
interceptor := &ResponseWriterInterceptor{ResponseWriter: w}
next.ServeHTTP(interceptor, r)
switch interceptor.status {
case http.StatusNotFound:
app.notFoundResponse(w, r)
case http.StatusMethodNotAllowed:
app.methodNotAllowedResponse(w, r)
}
})
}
更简洁的方法是直接使用自定义的 ServeMux:
type JSONServeMux struct {
*http.ServeMux
app *application
}
func (m *JSONServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
handler, pattern := m.Handler(r)
if pattern == "" {
m.app.notFoundResponse(w, r)
return
}
handler.ServeHTTP(w, r)
}
func (m *JSONServeMux) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) {
m.ServeMux.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet && pattern == r.URL.Path {
m.app.methodNotAllowedResponse(w, r)
return
}
handler(w, r)
})
}
使用示例:
mux := &JSONServeMux{
ServeMux: http.NewServeMux(),
app: app,
}
mux.HandleFunc("/api/users", app.handleUsers)
http.ListenAndServe(":8080", mux)
这种方法避免了中间件的复杂性,直接在路由层处理错误响应。

