mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
API: Permit Cache-Control (browser caching) for datasource resources (#62033)
* Start work on allowing certain resources to pass through Cache-Control headers. --------- Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
This commit is contained in:
parent
f9ec16e74f
commit
27d429e3b1
@ -26,21 +26,24 @@ func HandleNoCacheHeader(ctx *contextmodel.ReqContext) {
|
||||
}
|
||||
|
||||
func AddDefaultResponseHeaders(cfg *setting.Cfg) web.Handler {
|
||||
t := web.NewTree()
|
||||
t.Add("/api/datasources/uid/:uid/resources/*", nil)
|
||||
t.Add("/api/datasources/:id/resources/*", nil)
|
||||
return func(c *web.Context) {
|
||||
c.Resp.Before(func(w web.ResponseWriter) {
|
||||
// if response has already been written, skip.
|
||||
c.Resp.Before(func(w web.ResponseWriter) { // if response has already been written, skip.
|
||||
if w.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(c.Req.URL.Path, "/api/datasources/proxy/") {
|
||||
_, _, resourceURLMatch := t.Match(c.Req.URL.Path)
|
||||
resourceCachable := resourceURLMatch && allowCacheControl(c.Resp)
|
||||
if !strings.HasPrefix(c.Req.URL.Path, "/api/datasources/proxy/") && !resourceCachable {
|
||||
addNoCacheHeaders(c.Resp)
|
||||
}
|
||||
|
||||
if !cfg.AllowEmbedding {
|
||||
addXFrameOptionsDenyHeader(w)
|
||||
}
|
||||
|
||||
addSecurityHeaders(w, cfg)
|
||||
})
|
||||
}
|
||||
@ -95,3 +98,24 @@ func AddCustomResponseHeaders(cfg *setting.Cfg) web.Handler {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func allowCacheControl(rw web.ResponseWriter) bool {
|
||||
ccHeaderValues := rw.Header().Values("Cache-Control")
|
||||
|
||||
if len(ccHeaderValues) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
foundPrivate := false
|
||||
foundPublic := false
|
||||
for _, val := range ccHeaderValues {
|
||||
if val == "private" {
|
||||
foundPrivate = true
|
||||
}
|
||||
if val == "public" {
|
||||
foundPublic = true
|
||||
}
|
||||
}
|
||||
|
||||
return foundPrivate && !foundPublic && rw.Header().Get("X-Grafana-Cache") != ""
|
||||
}
|
||||
|
@ -154,6 +154,22 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
assert.Empty(t, sc.resp.Header().Get("Expires"))
|
||||
})
|
||||
|
||||
middlewareScenario(t, "middleware should pass cache-control on resources with private cache control", func(t *testing.T, sc *scenarioContext) {
|
||||
sc = sc.fakeReq("GET", "/api/datasources/1/resources/foo")
|
||||
sc.resp.Header().Add("Cache-Control", "private")
|
||||
sc.resp.Header().Add("X-Grafana-Cache", "true")
|
||||
sc.exec()
|
||||
assert.Equal(t, "private", sc.resp.Header().Get("Cache-Control"))
|
||||
})
|
||||
|
||||
middlewareScenario(t, "middleware should not pass cache-control on resources with public cache control", func(t *testing.T, sc *scenarioContext) {
|
||||
sc = sc.fakeReq("GET", "/api/datasources/1/resources/foo")
|
||||
sc.resp.Header().Add("Cache-Control", "public")
|
||||
sc.resp.Header().Add("X-Grafana-Cache", "true")
|
||||
sc.exec()
|
||||
assert.Equal(t, noStore, sc.resp.Header().Get("Cache-Control"))
|
||||
})
|
||||
|
||||
middlewareScenario(t, "middleware should not add Cache-Control header for requests to datasource proxy API", func(
|
||||
t *testing.T, sc *scenarioContext) {
|
||||
sc.fakeReq("GET", "/api/datasources/proxy/1/test").exec()
|
||||
|
@ -135,6 +135,7 @@ func (sc *scenarioContext) exec() {
|
||||
Value: sc.tokenSessionCookie,
|
||||
})
|
||||
}
|
||||
|
||||
sc.m.ServeHTTP(sc.resp, sc.req)
|
||||
|
||||
if sc.resp.Header().Get("Content-Type") == "application/json; charset=UTF-8" {
|
||||
|
Loading…
Reference in New Issue
Block a user