From 74093c700f850cf43e68adb79c499a1abdb0fb66 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Tue, 4 Jul 2017 16:33:37 +0200 Subject: [PATCH] api: adds no-cache header for GET requests Fixes #5356. Internet Explorer aggressively caches GET requests which means that all API calls fetching data are cached. This fix adds a Cache-Control header with the value no-cache to all GET requests to the API. --- pkg/api/http_server.go | 2 ++ pkg/middleware/middleware.go | 8 ++++++++ pkg/middleware/middleware_test.go | 11 +++++++++++ 3 files changed, 21 insertions(+) diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index 0468b5cbe8a..4873062a933 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -171,6 +171,8 @@ func (hs *HttpServer) newMacaron() *macaron.Macaron { m.Use(middleware.ValidateHostHeader(setting.Domain)) } + m.Use(middleware.AddDefaultResponseHeaders()) + return m } diff --git a/pkg/middleware/middleware.go b/pkg/middleware/middleware.go index 5aafe12d374..2a1d3e080a5 100644 --- a/pkg/middleware/middleware.go +++ b/pkg/middleware/middleware.go @@ -245,3 +245,11 @@ func (ctx *Context) HasHelpFlag(flag m.HelpFlags1) bool { func (ctx *Context) TimeRequest(timer metrics.Timer) { ctx.Data["perfmon.timer"] = timer } + +func AddDefaultResponseHeaders() macaron.Handler { + return func(ctx *Context) { + if ctx.IsApiRequest() && ctx.Req.Method == "GET" { + ctx.Resp.Header().Add("Cache-Control", "no-cache") + } + } +} diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index a1836a6744e..f18261e478d 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -30,6 +30,16 @@ func TestMiddlewareContext(t *testing.T) { So(sc.resp.Code, ShouldEqual, 200) }) + middlewareScenario("middleware should add Cache-Control header for GET requests to API", func(sc *scenarioContext) { + sc.fakeReq("GET", "/api/search").exec() + So(sc.resp.Header().Get("Cache-Control"), ShouldEqual, "no-cache") + }) + + middlewareScenario("middleware should not add Cache-Control header to for non-API GET requests", func(sc *scenarioContext) { + sc.fakeReq("GET", "/").exec() + So(sc.resp.Header().Get("Cache-Control"), ShouldBeEmpty) + }) + middlewareScenario("Non api request should init session", func(sc *scenarioContext) { sc.fakeReq("GET", "/").exec() So(sc.resp.Header().Get("Set-Cookie"), ShouldContainSubstring, "grafana_sess") @@ -327,6 +337,7 @@ func middlewareScenario(desc string, fn scenarioFunc) { startSessionGC = func() {} sc.m.Use(Sessioner(&session.Options{})) sc.m.Use(OrgRedirect()) + sc.m.Use(AddDefaultResponseHeaders()) sc.defaultHandler = func(c *Context) { sc.context = c