duan4739 2018-02-20 00:46
浏览 174
已采纳

大猩猩/ mux golang缓存静态文件

I have a go web app which serves static HTML/JS/CSS files plus has some API endpoints. I noticed that my HTML/JS/CSS are not being cached on the browser. E.g., every time I reload a page, they are fully re-downloaded.

Is this a server side configuration change that I need to set? How can I accomplish this with Go and Gorilla Mux?

I'm using Google App Engine, so Nginx is not a possibility.

Here's my main.go code:

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)
}

EDIT: Here's the solution with @Topo's suggestion:

   // 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)
    })
}
  • 写回答

1条回答 默认 最新

  • dqh1984 2018-02-20 01:53
    关注

    To tell the browser to cache your files, you need to tell it for how long, if not the user would never see newer versions of the file.

    To do this just set the Cache-Control header inside your handler function:

    w.Header().Set("Cache-Control", "max-age=3600")
    

    It's also a good idea to use the Etag header to let the browsers know when there is a new version of the file. That way you can cache the files for a really long time, and still serve the new content to the users as soon as it's available:

    etag := "some unique value"
    w.Header().Set("Etag", etag)
    

    You need to use a different etag value every time the file changes. The browser stores it and only reloads the file when the etag is different to the stored value. You can use something like the file name + modified date for the 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)
    

    You can read the mozilla docs for the Cache-Control and Etag heders.

    If you want to avoid writing your own handler function for static files and instead keep using http.FileServer, you will need to wrap it in a handler that sets the headers before writing the response. Here is a blog post on wrapping web handlers.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 AT89C51控制8位八段数码管显示时钟。
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题