From e2544597a1f5fe0842012bbbde29213745844ea7 Mon Sep 17 00:00:00 2001 From: spacewander Date: Sat, 8 Jul 2017 11:09:05 +0800 Subject: [PATCH] gzip: change ETag to weak ETag after gzip According to https://tools.ietf.org/html/rfc7232#section-2.1 > Likewise, a validator is weak if it is shared by two or more representations of a given resource at the same time, unless those representations have identical representation data. For example, if the origin server sends the same validator for a representation with a gzip content coding applied as it does for a representation with no content coding, then that validator is weak. Therefore, after gzip, we should change the original etag to weak etag. --- caddyhttp/gzip/gzip.go | 4 ++++ caddyhttp/gzip/gzip_test.go | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/caddyhttp/gzip/gzip.go b/caddyhttp/gzip/gzip.go index 110b704a..bd8692cd 100644 --- a/caddyhttp/gzip/gzip.go +++ b/caddyhttp/gzip/gzip.go @@ -105,6 +105,10 @@ func (w *gzipResponseWriter) WriteHeader(code int) { w.Header().Del("Content-Length") w.Header().Set("Content-Encoding", "gzip") w.Header().Add("Vary", "Accept-Encoding") + originalEtag := w.Header().Get("ETag") + if originalEtag != "" && !strings.HasPrefix(originalEtag, "W/") { + w.Header().Set("ETag", "W/"+originalEtag) + } w.ResponseWriterWrapper.WriteHeader(code) w.statusCodeWritten = true } diff --git a/caddyhttp/gzip/gzip_test.go b/caddyhttp/gzip/gzip_test.go index cc6e571b..494dec62 100644 --- a/caddyhttp/gzip/gzip_test.go +++ b/caddyhttp/gzip/gzip_test.go @@ -38,6 +38,14 @@ func TestGzipHandler(t *testing.T) { t.Error(err) } r.Header.Set("Accept-Encoding", "gzip") + w.Header().Set("ETag", `"2n9cd"`) + _, err = gz.ServeHTTP(w, r) + if err != nil { + t.Error(err) + } + + // The second pass, test if the ETag is already weak + w.Header().Set("ETag", `W/"2n9cd"`) _, err = gz.ServeHTTP(w, r) if err != nil { t.Error(err) @@ -114,6 +122,10 @@ func nextFunc(shouldGzip bool) httpserver.Handler { if w.Header().Get("Vary") != "Accept-Encoding" { return 0, fmt.Errorf("Vary must be Accept-Encoding, found %v", w.Header().Get("Vary")) } + etag := w.Header().Get("ETag") + if etag != "" && etag != `W/"2n9cd"` { + return 0, fmt.Errorf("ETag must be converted to weak Etag, found %v", w.Header().Get("ETag")) + } if _, ok := w.(*gzipResponseWriter); !ok { return 0, fmt.Errorf("ResponseWriter should be gzipResponseWriter, found %T", w) }