diff --git a/static.go b/static.go index 593e474..7f2adfb 100644 --- a/static.go +++ b/static.go @@ -178,8 +178,12 @@ func staticHandler(ctx *Context, log *log.Logger, opt StaticOptions) bool { } if opt.ETag { - tag := GenerateETag(string(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat)) - ctx.Resp.Header().Set("ETag", `"`+tag+`"`) + tag := `"` + GenerateETag(string(fi.Size()), fi.Name(), fi.ModTime().UTC().Format(http.TimeFormat)) + `"` + ctx.Resp.Header().Set("ETag", tag) + if ctx.Req.Header.Get("If-None-Match") == tag { + ctx.Resp.WriteHeader(http.StatusNotModified) + return true + } } http.ServeContent(ctx.Resp, ctx.Req.Request, file, fi.ModTime(), f) diff --git a/static_test.go b/static_test.go index 27a7dd1..2e06acc 100644 --- a/static_test.go +++ b/static_test.go @@ -176,8 +176,7 @@ func Test_Static_Options(t *testing.T) { }) Convey("Serve static files with options expires", t, func() { - var buf bytes.Buffer - m := NewWithLogger(&buf) + m := New() opt := StaticOptions{Expires: func() string { return "46" }} m.Use(Static(currentRoot, opt)) @@ -190,8 +189,7 @@ func Test_Static_Options(t *testing.T) { }) Convey("Serve static files with options ETag", t, func() { - var buf bytes.Buffer - m := NewWithLogger(&buf) + m := New() opt := StaticOptions{ETag: true} m.Use(Static(currentRoot, opt)) @@ -203,6 +201,26 @@ func Test_Static_Options(t *testing.T) { So(resp.Header().Get("ETag"), ShouldEqual, `"`+tag+`"`) }) + + Convey("Serve static files with ETag in If-None-Match", t, func() { + m := New() + opt := StaticOptions{ETag: true} + m.Use(Static(currentRoot, opt)) + + resp := httptest.NewRecorder() + req, err := http.NewRequest("GET", "http://localhost:4000/macaron.go", nil) + So(err, ShouldBeNil) + m.ServeHTTP(resp, req) + tag := GenerateETag(string(resp.Body.Len()), "macaron.go", resp.Header().Get("last-modified")) + + // Second request with ETag in If-None-Match + resp = httptest.NewRecorder() + req.Header.Add("If-None-Match", `"`+tag+`"`) + m.ServeHTTP(resp, req) + + So(resp.Code, ShouldEqual, http.StatusNotModified) + So(len(resp.Body.Bytes()), ShouldEqual, 0) + }) } func Test_Static_Redirect(t *testing.T) {