【问题标题】:Go webserver - don't cache files using timestampGo webserver - 不要使用时间戳缓存文件
【发布时间】:2015-11-24 05:47:35
【问题描述】:

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

网络服务器代码使用 http.FileServer() 和 http.ListenAndServe()。

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

touch -d"23:59" index.html

重新加载页面,然后

touch -d"23:58" index.html

这次重新加载会在 index.html 上给出 304 响应。

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

【问题讨论】:

    标签: caching go webserver


    【解决方案1】:

    假设您的文件服务器代码类似于example in the docs

    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("/static"))))
    

    您可以编写一个处理程序来设置适当的缓存标头以通过剥离 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)
    }
    

    像这样使用它:

    http.Handle("/static/", NoCache(http.StripPrefix("/static/", http.FileServer(http.Dir("/static")))))
    

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

    【讨论】:

    • 我已经在 index.html 中设置了无缓存标头,但似乎是通过在检查标头之前查看文件时间戳来做出决定。
    • 您的浏览器/HTTP 客户端无法“看到”时间戳,但是是的,http.FileServer 将通过serveContent here 设置它,并将根据@987654324 设置Last-Modified 标头@。另一种选择是直接在您自己的处理程序中调用http.ServeContent,并将time.Now() 作为modTime 传递。
    猜你喜欢
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    • 2015-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多