缓存控制和Etag在Google Chrome上不被接受

时间:2018-10-12 16:51:51

标签: http caching http-headers

我已经在我开发的URL缩短API中实现了Google描述的HTTP Caching guidelines

这是我发送回复的方式:

const urlResponseCacheControlMaxAge = 172800 // 2 days

type urlResponse struct {
    LongURL  string `json:"longUrl"`
    ShortURL string `json:"shortUrl"`
}

func (u urlResponse) Hash() string {
    parts := strings.Split(u.ShortURL, "/")
    return parts[len(parts)-1]
}

func sendURLResponse(w http.ResponseWriter, req *http.Request, urlResponse *urlResponse) {

    if eTag, ok := req.Header["ETag"]; ok && urlResponse.Hash() == eTag[0] {
        w.WriteHeader(http.StatusNotModified)
        io.WriteString(w, "")
        return
    }

    cacheControl := fmt.Sprintf(
        "max-age:%d, public",
        urlResponseCacheControlMaxAge,
    )

    w.Header().Set("Cache-Control", cacheControl)
    w.Header().Set("Content-Type", "application/json;charset=utf-8")
    w.Header().Set("ETag", urlResponse.Hash())
    w.WriteHeader(http.StatusOK)
    encoder := json.NewEncoder(w)
    err := encoder.Encode(urlResponse)

    if err != nil {
        SendError(w, NewError(
            URLResponseEncoding,
            "Error encoding response",
            map[string]string{"error": err.Error()},
        ))
        return
    }
}

基本上,当浏览器向API发送请求(使用GET)时,我在响应中返回ETag和Cache-Control标头;缓存控制标头将最长有效期设置为两天。

我希望发生的是,在后续请求中,浏览器使用了缓存的响应。两天后,浏览器应在请求标头中发送ETag,以检查响应是否已更改。

但是,我观察到的是每次我单击“提交”按钮时,浏览器都会重新发送请求。在Google Chrome开发者控制台上,我未选中“禁用缓存”,但每次仍然发送请求。

此外,浏览器没有将ETag和请求标头一起发送回去。

是否缺少某些导致缓存无法按预期工作的东西?

2 个答案:

答案 0 :(得分:2)

cacheControl := fmt.Sprintf(
    "max-age:%d, public",

Cache-Control标头必须包含使用时的max-age=...而不是max-age:...的缓存时间(=:)。您尝试以错误的方式设置的值将被忽略。

  

此外,浏览器不会将ETag和请求标头一起发回。

if eTag, ok := req.Header["ETag"]; ok && urlResponse.Hash() == eTag[0] {
    w.WriteHeader(http.StatusNotModified)

浏览器不会在ETag标头内发送回etag。此标头仅用于设置etag。相反,浏览器将要求服务器提供资源是否经过了比较比较,并通过将接收到的etag放入If-None-Match: ...标头中来实现-含义:如果资源与给定etag不匹配,请返回资源。 / p>

答案 1 :(得分:0)

要使用 ETag 和浏览器发送 If-Modified-SinceIf-None-Match 标头,缓存控件必须设置为 no-cache

服务器使用 Cache-Control: no-cache header 或浏览器通过 Request.cache option