mirror of
https://github.com/grafana/grafana.git
synced 2024-11-22 08:56:43 -06:00
Middleware: Add Custom Headers to HTTP responses (#59018)
* Middleware: Add Custom Headers to HTTP responses * Update docs/sources/setup-grafana/configure-grafana/_index.md Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com> * Update conf/defaults.ini Co-authored-by: Dave Henderson <dave.henderson@grafana.com> * Update conf/sample.ini Co-authored-by: Dave Henderson <dave.henderson@grafana.com> * Update _index.md Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com> Co-authored-by: Dave Henderson <dave.henderson@grafana.com>
This commit is contained in:
parent
9cdb6b07c7
commit
bba42b113c
@ -85,6 +85,11 @@ cdn_url =
|
||||
# `0` means there is no timeout for reading the request.
|
||||
read_timeout = 0
|
||||
|
||||
# This setting enables you to specify additional headers that the server adds to HTTP(S) responses.
|
||||
[server.custom_response_headers]
|
||||
#exampleHeader1 = exampleValue1
|
||||
#exampleHeader2 = exampleValue2
|
||||
|
||||
#################################### Database ############################
|
||||
[database]
|
||||
# You can configure the database connection by specifying type, host, name, user and password
|
||||
|
@ -86,6 +86,11 @@
|
||||
# `0` means there is no timeout for reading the request.
|
||||
;read_timeout = 0
|
||||
|
||||
# This setting enables you to specify additional headers that the server adds to HTTP(S) responses.
|
||||
[server.custom_response_headers]
|
||||
#exampleHeader1 = exampleValue1
|
||||
#exampleHeader2 = exampleValue2
|
||||
|
||||
#################################### Database ####################################
|
||||
[database]
|
||||
# You can configure the database connection by specifying type, host, name, user and password
|
||||
|
@ -292,6 +292,17 @@ Sets the maximum time using a duration format (5s/5m/5ms) before timing out read
|
||||
|
||||
<hr />
|
||||
|
||||
## [server.custom_response_headers]
|
||||
|
||||
This setting enables you to specify additional headers that the server adds to HTTP(S) responses.
|
||||
|
||||
```
|
||||
exampleHeader1 = exampleValue1
|
||||
exampleHeader2 = exampleValue2
|
||||
```
|
||||
|
||||
<hr />
|
||||
|
||||
## [database]
|
||||
|
||||
Grafana needs a database to store users and dashboards (and other
|
||||
|
@ -598,6 +598,10 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
|
||||
hs.mapStatic(m, hs.Cfg.ImagesDir, "", "/public/img/attachments")
|
||||
}
|
||||
|
||||
if len(hs.Cfg.CustomResponseHeaders) > 0 {
|
||||
m.Use(middleware.AddCustomResponseHeaders(hs.Cfg))
|
||||
}
|
||||
|
||||
m.Use(middleware.AddDefaultResponseHeaders(hs.Cfg))
|
||||
|
||||
if hs.Cfg.ServeFromSubPath && hs.Cfg.AppSubURL != "" {
|
||||
|
@ -77,3 +77,21 @@ func addNoCacheHeaders(w web.ResponseWriter) {
|
||||
func addXFrameOptionsDenyHeader(w web.ResponseWriter) {
|
||||
w.Header().Set("X-Frame-Options", "deny")
|
||||
}
|
||||
|
||||
func AddCustomResponseHeaders(cfg *setting.Cfg) web.Handler {
|
||||
return func(c *web.Context) {
|
||||
c.Resp.Before(func(w web.ResponseWriter) {
|
||||
if w.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
for header, value := range cfg.CustomResponseHeaders {
|
||||
// do not override existing headers
|
||||
if w.Header().Get(header) != "" {
|
||||
continue
|
||||
}
|
||||
w.Header().Set(header, value)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -514,6 +514,17 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
cfg.AnonymousOrgRole = string(org.RoleEditor)
|
||||
})
|
||||
|
||||
middlewareScenario(t, "middleware should add custom response headers", func(t *testing.T, sc *scenarioContext) {
|
||||
sc.fakeReq("GET", "/api/").exec()
|
||||
assert.Regexp(t, "test", sc.resp.Header().Get("X-Custom-Header"))
|
||||
assert.Regexp(t, "other-test", sc.resp.Header().Get("X-Other-Header"))
|
||||
}, func(cfg *setting.Cfg) {
|
||||
cfg.CustomResponseHeaders = map[string]string{
|
||||
"X-Custom-Header": "test",
|
||||
"X-Other-Header": "other-test",
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("auth_proxy", func(t *testing.T) {
|
||||
const userID int64 = 33
|
||||
const orgID int64 = 4
|
||||
@ -811,6 +822,7 @@ func middlewareScenario(t *testing.T, desc string, fn scenarioFunc, cbs ...func(
|
||||
require.Truef(t, exists, "Views directory should exist at %q", viewsPath)
|
||||
|
||||
sc.m = web.New()
|
||||
sc.m.Use(AddCustomResponseHeaders(cfg))
|
||||
sc.m.Use(AddDefaultResponseHeaders(cfg))
|
||||
sc.m.UseMiddleware(ContentSecurityPolicy(cfg, logger))
|
||||
sc.m.UseMiddleware(web.Renderer(viewsPath, "[[", "]]"))
|
||||
|
@ -486,6 +486,8 @@ type Cfg struct {
|
||||
GRPCServerNetwork string
|
||||
GRPCServerAddress string
|
||||
GRPCServerTLSConfig *tls.Config
|
||||
|
||||
CustomResponseHeaders map[string]string
|
||||
}
|
||||
|
||||
type CommandLineArgs struct {
|
||||
@ -1692,6 +1694,14 @@ func (cfg *Cfg) readServerSettings(iniFile *ini.File) error {
|
||||
|
||||
cfg.ReadTimeout = server.Key("read_timeout").MustDuration(0)
|
||||
|
||||
headersSection := cfg.Raw.Section("server.custom_response_headers")
|
||||
keys := headersSection.Keys()
|
||||
cfg.CustomResponseHeaders = make(map[string]string, len(keys))
|
||||
|
||||
for _, key := range keys {
|
||||
cfg.CustomResponseHeaders[key.Name()] = key.Value()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user