转到网络服务器 - 不要使用时间戳缓存文件

eye*_*ver 4 webserver caching go

我正在运行一个用嵌入式系统编写的网络服务器.如果某人降级了固件版本,index.html的时间戳可能会倒退.如果index.html比先前版本旧,则服务器发送http 304响应(未修改),并提供该文件的缓存版本.

Web服务器代码使用http.FileServer()和http.ListenAndServe().

通过使用Posix命令修改index.html的时间戳,可以轻松地重现该问题 touch

touch -d"23:59" index.html
Run Code Online (Sandbox Code Playgroud)

然后重新加载页面

touch -d"23:58" index.html
Run Code Online (Sandbox Code Playgroud)

重新加载这个时间将在index.html上给出304响应.

有没有办法防止基于时间戳的缓存?

eli*_*rar 11

假设您的文件服务器代码与文档中示例类似:

http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("/static"))))
Run Code Online (Sandbox Code Playgroud)

您可以编写一个处理程序来设置相应的缓存标头,以通过剥离ETag标头和设置Cache-Control: no-cache, private, max-age=0以防止缓存(本地和上游代理)来防止此行为:

var epoch = time.Unix(0, 0).Format(time.RFC1123)

var noCacheHeaders = map[string]string{
    "Expires":         epoch,
    "Cache-Control":   "no-cache, private, max-age=0",
    "Pragma":          "no-cache",
    "X-Accel-Expires": "0",
}

var etagHeaders = []string{
    "ETag",
    "If-Modified-Since",
    "If-Match",
    "If-None-Match",
    "If-Range",
    "If-Unmodified-Since",
}

func NoCache(h http.Handler) http.Handler {
    fn := func(w http.ResponseWriter, r *http.Request) {
        // Delete any ETag headers that may have been set
        for _, v := range etagHeaders {
            if r.Header.Get(v) != "" {
                r.Header.Del(v)
            }
        }

        // Set our NoCache headers
        for k, v := range noCacheHeaders {
            w.Header().Set(k, v)
        }

        h.ServeHTTP(w, r)
    }

    return http.HandlerFunc(fn)
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

http.Handle("/static/", NoCache(http.StripPrefix("/static/", http.FileServer(http.Dir("/static")))))
Run Code Online (Sandbox Code Playgroud)

注意:我最初是在github.com/zenazn/goji/middleware上写的,所以你也可以导入它,但这是一段简单的代码,我想为后代展示一个完整的例子!