Golang 标准库net/http自定义404页面,通过中间件的形式来实现。
type hijack404 struct {
http.ResponseWriter
R *http.Request
Handle404 func(w http.ResponseWriter, r *http.Request) bool
}
// WriteHeader WriteHeader
func (h *hijack404) WriteHeader(code int) {
if 404 == code && h.Handle404(h.ResponseWriter, h.R) {
panic(h)
}
h.ResponseWriter.WriteHeader(code)
}
// Middle404Handler Middle404Handler
func Middle404Handler(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
hijack := &hijack404{w, r, Page404Handler}
defer func() {
if p := recover(); p != nil {
if p == hijack {
return
}
panic(p)
}
}()
handler.ServeHTTP(hijack, r)
})
}
// Page404Handler Page404Handler
func Page404Handler(w http.ResponseWriter, r *http.Request) bool {
ctx, err := ioutil.ReadFile("404.html")
if err != nil {
log.Printf("file not found %s", err.Error())
return false
}
if _, ok := w.Header()["Content-Length"]; ok {
w.Header().Set("Content-Length", strconv.Itoa(len(string(ctx))))
} else {
w.Header().Add("Content-Length", strconv.Itoa(len(string(ctx))))
}
if _, ok := w.Header()["Content-Type"]; ok {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
} else {
w.Header().Add("Content-Type", "text/html; charset=utf-8")
}
w.WriteHeader(404)
w.Write(ctx)
return true
}
其它实现方式参考:https://stackoverflow.com/questions/31535569/golang-how-to-read-response-body-of-reverseproxy