gorilla/mux golang缓存静态文件
gorilla/mux golang cache static files
我有一个 go web 应用程序,它提供静态 HTML/JS/CSS 文件,还有一些 API 端点。我注意到我的 HTML/JS/CSS 没有被缓存在浏览器上。例如,每次我重新加载页面时,它们都会被完全重新下载。
这是我需要设置的服务器端配置更改吗?我如何使用 Go 和 Gorilla Mux 完成此操作?
我正在使用 Google App Engine,所以 Nginx 是不可能的。
这是我的 main.go 代码:
package main
import (
"associations"
"html/template"
"net/http"
"log"
"io/ioutil"
"github.com/gorilla/mux"
"github.com/rs/cors"
"google.golang.org/appengine"
"google.golang.org/appengine/mail"
)
var index = template.Must(template.ParseFiles(
"dist/index.html",
))
func init() {
r := mux.NewRouter()
r.HandleFunc("/", homeHandler)
r.HandleFunc("/api/{tenant}/certificates", associations.GetCertificate).Methods("GET")
r.HandleFunc("/api/{tenant}/requests", associations.PostRequest).Methods("POST")
// handle static files
r.PathPrefix("/static/").Handler(
http.StripPrefix("/static/", http.FileServer(http.Dir("dist/static/"))))
r.NotFoundHandler = http.HandlerFunc(homeHandler) // work around for SPA serving index.html
handler := cors.Default().Handler(r)
http.Handle("/", handler)
}
编辑:这是@Topo 建议的解决方案:
// handle static files
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/",
CacheControlWrapper(http.FileServer(http.Dir("dist/static/")))))
....
func CacheControlWrapper(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=2592000") // 30 days
h.ServeHTTP(w, r)
})
}
要告诉浏览器缓存您的文件,您需要告诉它缓存多长时间,否则用户将永远不会看到该文件的更新版本。
要做到这一点,只需在处理函数中设置 Cache-Control
header:
w.Header().Set("Cache-Control", "max-age=3600")
使用 Etag header 让浏览器知道何时有文件的新版本也是一个好主意。这样您就可以将文件缓存很长时间,并在新内容可用时立即向用户提供新内容:
etag := "some unique value"
w.Header().Set("Etag", etag)
每次文件更改时,您都需要使用不同的 etag 值。浏览器存储它,只有当 etag 与存储值不同时才重新加载文件。您可以为 etag 使用类似文件名 + 修改日期的内容:
var modTime time.Time
fi, err := fh.Stat()
if err == nil {
modTime = fi.ModTime()
} else {
modTime = time.Now()
}
etag := "\"" + file + modTime.String() + "\""
w.Header().Set("Etag", etag)
您可以阅读 Cache-Control and Etag heders 的 mozilla 文档。
如果您想避免为静态文件编写自己的处理程序函数,而是继续使用 http.FileServer
,您需要将其包装在一个处理程序中,在编写响应之前设置 headers . Here 是一篇关于包装网络处理程序的博客 post。
我有一个 go web 应用程序,它提供静态 HTML/JS/CSS 文件,还有一些 API 端点。我注意到我的 HTML/JS/CSS 没有被缓存在浏览器上。例如,每次我重新加载页面时,它们都会被完全重新下载。
这是我需要设置的服务器端配置更改吗?我如何使用 Go 和 Gorilla Mux 完成此操作?
我正在使用 Google App Engine,所以 Nginx 是不可能的。
这是我的 main.go 代码:
package main
import (
"associations"
"html/template"
"net/http"
"log"
"io/ioutil"
"github.com/gorilla/mux"
"github.com/rs/cors"
"google.golang.org/appengine"
"google.golang.org/appengine/mail"
)
var index = template.Must(template.ParseFiles(
"dist/index.html",
))
func init() {
r := mux.NewRouter()
r.HandleFunc("/", homeHandler)
r.HandleFunc("/api/{tenant}/certificates", associations.GetCertificate).Methods("GET")
r.HandleFunc("/api/{tenant}/requests", associations.PostRequest).Methods("POST")
// handle static files
r.PathPrefix("/static/").Handler(
http.StripPrefix("/static/", http.FileServer(http.Dir("dist/static/"))))
r.NotFoundHandler = http.HandlerFunc(homeHandler) // work around for SPA serving index.html
handler := cors.Default().Handler(r)
http.Handle("/", handler)
}
编辑:这是@Topo 建议的解决方案:
// handle static files
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/",
CacheControlWrapper(http.FileServer(http.Dir("dist/static/")))))
....
func CacheControlWrapper(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=2592000") // 30 days
h.ServeHTTP(w, r)
})
}
要告诉浏览器缓存您的文件,您需要告诉它缓存多长时间,否则用户将永远不会看到该文件的更新版本。
要做到这一点,只需在处理函数中设置 Cache-Control
header:
w.Header().Set("Cache-Control", "max-age=3600")
使用 Etag header 让浏览器知道何时有文件的新版本也是一个好主意。这样您就可以将文件缓存很长时间,并在新内容可用时立即向用户提供新内容:
etag := "some unique value"
w.Header().Set("Etag", etag)
每次文件更改时,您都需要使用不同的 etag 值。浏览器存储它,只有当 etag 与存储值不同时才重新加载文件。您可以为 etag 使用类似文件名 + 修改日期的内容:
var modTime time.Time
fi, err := fh.Stat()
if err == nil {
modTime = fi.ModTime()
} else {
modTime = time.Now()
}
etag := "\"" + file + modTime.String() + "\""
w.Header().Set("Etag", etag)
您可以阅读 Cache-Control and Etag heders 的 mozilla 文档。
如果您想避免为静态文件编写自己的处理程序函数,而是继续使用 http.FileServer
,您需要将其包装在一个处理程序中,在编写响应之前设置 headers . Here 是一篇关于包装网络处理程序的博客 post。