我正在嵌入式系统上运行一个用 go 编写的网络服务器。如果有人降级了固件版本,index.html 的时间戳可能会倒退。如果index.html比以前的版本旧,服务器会发送http 304响应(未修改),并提供文件的缓存版本。
网络服务器代码使用http.FileServer()和http.ListenAndServe()。
通过使用 Posix 命令修改 index.html 的时间戳,可以轻松重现该问题
touch
touch -d"23:59" index.html
重新加载页面,然后
touch -d"23:58" index.html
这次重新加载将会在index.html上给出304响应。
有没有办法阻止基于时间戳的缓存?
假设您的文件服务器代码类似于文档中的示例:
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 上写的,所以你也可以导入它,但这是一段简单的代码,我想为后代展示一个完整的示例!
解决该问题的另一种方法是向响应添加 etag 标头。 etag 的存在将使浏览器使用它,并忽略最后的修改日期。
此答案中的更多详细信息:https://stackoverflow.com/a/48876760/164802