2 回答
TA贡献1895条经验 获得超3个赞
为了使中间件与 . 解耦,http.FileServer
在包装它时,您可以传递一个特定的实现http.ResponseWriter
:
累积标头,以防它们需要被丢弃(如果
WriteHeader
使用 404 调用)如果
WriteHeader
使用 404 调用:取消累积的标题
发送自定义 404
忽略
Write
来自包装处理程序的调用如果
WriteHeader
未调用,或使用非 404 调用,则:将累积的标头发送到真实的
ResponseWriter
WriteHeader
将andWrite
呼叫路由到真实的ResponseWriter
type notFoundInterceptorWriter struct {
rw http.ResponseWriter // set to nil to signal a 404 has been intercepted
h http.Header // set to nil to signal headers have been emitted
notFoundHandler http.Handler
r *http.Request
}
func (rw *notFoundInterceptorWriter) Header() http.Header {
if rw.h == nil && rw.rw != nil {
return rw.rw.Header()
}
return rw.h
}
func (rw *notFoundInterceptorWriter) WriteHeader(status int) {
if status == http.StatusNotFound {
rw.notFoundHandler.ServeHTTP(rw.rw, rw.r)
rw.rw = nil
} else {
for k, vs := range rw.h {
for _, v := range vs {
rw.rw.Header().Add(k, v)
}
}
rw.rw.WriteHeader(status)
}
rw.h = nil
}
func (rw *notFoundInterceptorWriter) Write(b []byte) (int, error) {
if rw.rw != nil {
return rw.rw.Write(b)
}
// ignore, so do as if everything was written OK
return len(b), nil
}
func StaticSiteHandler(h, notFoundHandler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w = ¬FoundInterceptorWriter{
rw: w,
h: make(http.Header),
notFoundHandler: notFoundHandler,
r: r,
}
h.ServeHTTP(w, r)
})
}
TA贡献1790条经验 获得超9个赞
您可以在提供文件之前统计文件以查看它是否存在。根据需要调整 404 处理程序(发出模板等)
package main
import (
"net/http"
"path"
"os"
)
func init() {
http.Handle("/", staticHandler)
}
func error404Handler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "404 not found", http.StatusNotFound)
}
func staticHandler(w http.ResponseWriter, r *http.Request) {
name := path.Clean(r.URL.Path)
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
error404Handler(w, r)
return
}
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
return http.ServeFile(w, r, name)
}
- 2 回答
- 0 关注
- 436 浏览
添加回答
举报