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:
Kyle Brandt
2023-02-02 20:34:55 +00:00
committed by GitHub
co-authored by Marcus Efraimsson
parent f9ec16e74f
commit 27d429e3b1
3 changed files with 45 additions and 4 deletions
+28 -4
View File
@@ -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") != ""
}