Skip to content

Commit 12661e8

Browse files
aknuds1sakjurwbrowne
authored
Move middleware context handler logic to service (grafana#29605)
* middleware: Move context handler to own service Signed-off-by: Arve Knudsen <[email protected]> Co-authored-by: Emil Tullsted <[email protected]> Co-authored-by: Will Browne <[email protected]>
1 parent d0f52d5 commit 12661e8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1323
-1081
lines changed

pkg/api/admin_users_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const (
2222
func TestAdminAPIEndpoint(t *testing.T) {
2323
const role = models.ROLE_ADMIN
2424

25-
t.Run("Given a server admin attempts to remove themself as an admin", func(t *testing.T) {
25+
t.Run("Given a server admin attempts to remove themselves as an admin", func(t *testing.T) {
2626
updateCmd := dtos.AdminUpdateUserPermissionsForm{
2727
IsGrafanaAdmin: false,
2828
}

pkg/api/api.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func (hs *HTTPServer) registerRoutes() {
1818
reqEditorRole := middleware.ReqEditorRole
1919
reqOrgAdmin := middleware.ReqOrgAdmin
2020
reqCanAccessTeams := middleware.AdminOrFeatureEnabled(hs.Cfg.EditorsCanAdmin)
21-
reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn()
21+
reqSnapshotPublicModeOrSignedIn := middleware.SnapshotPublicModeOrSignedIn(hs.Cfg)
2222
redirectFromLegacyDashboardURL := middleware.RedirectFromLegacyDashboardURL()
2323
redirectFromLegacyDashboardSoloURL := middleware.RedirectFromLegacyDashboardSoloURL()
2424
redirectFromLegacyPanelEditURL := middleware.RedirectFromLegacyPanelEditURL()

pkg/api/common.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func Success(message string) *NormalResponse {
8585
return JSON(200, resp)
8686
}
8787

88-
// Error create a erroneous response
88+
// Error creates an error response.
8989
func Error(status int, message string, err error) *NormalResponse {
9090
data := make(map[string]interface{})
9191

pkg/api/common_test.go

+57-4
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@ import (
88
"testing"
99

1010
"github.com/grafana/grafana/pkg/bus"
11-
"github.com/grafana/grafana/pkg/middleware"
11+
"github.com/grafana/grafana/pkg/infra/remotecache"
1212
"github.com/grafana/grafana/pkg/models"
13+
"github.com/grafana/grafana/pkg/registry"
1314
"github.com/grafana/grafana/pkg/services/auth"
15+
"github.com/grafana/grafana/pkg/services/contexthandler"
16+
"github.com/grafana/grafana/pkg/services/rendering"
17+
"github.com/grafana/grafana/pkg/services/sqlstore"
18+
"github.com/grafana/grafana/pkg/setting"
1419
"github.com/stretchr/testify/require"
1520
"gopkg.in/macaron.v1"
1621
)
@@ -141,20 +146,68 @@ func (sc *scenarioContext) exec() {
141146
type scenarioFunc func(c *scenarioContext)
142147
type handlerFunc func(c *models.ReqContext) Response
143148

149+
func getContextHandler(t *testing.T) *contexthandler.ContextHandler {
150+
t.Helper()
151+
152+
sqlStore := sqlstore.InitTestDB(t)
153+
remoteCacheSvc := &remotecache.RemoteCache{}
154+
cfg := setting.NewCfg()
155+
cfg.RemoteCacheOptions = &setting.RemoteCacheOptions{
156+
Name: "database",
157+
}
158+
userAuthTokenSvc := auth.NewFakeUserAuthTokenService()
159+
renderSvc := &fakeRenderService{}
160+
ctxHdlr := &contexthandler.ContextHandler{}
161+
162+
err := registry.BuildServiceGraph([]interface{}{cfg}, []*registry.Descriptor{
163+
{
164+
Name: sqlstore.ServiceName,
165+
Instance: sqlStore,
166+
},
167+
{
168+
Name: remotecache.ServiceName,
169+
Instance: remoteCacheSvc,
170+
},
171+
{
172+
Name: auth.ServiceName,
173+
Instance: userAuthTokenSvc,
174+
},
175+
{
176+
Name: rendering.ServiceName,
177+
Instance: renderSvc,
178+
},
179+
{
180+
Name: contexthandler.ServiceName,
181+
Instance: ctxHdlr,
182+
},
183+
})
184+
require.NoError(t, err)
185+
186+
return ctxHdlr
187+
}
188+
144189
func setupScenarioContext(t *testing.T, url string) *scenarioContext {
145190
sc := &scenarioContext{
146191
url: url,
147192
t: t,
148193
}
149-
viewsPath, _ := filepath.Abs("../../public/views")
194+
viewsPath, err := filepath.Abs("../../public/views")
195+
require.NoError(t, err)
150196

151197
sc.m = macaron.New()
152198
sc.m.Use(macaron.Renderer(macaron.RenderOptions{
153199
Directory: viewsPath,
154200
Delims: macaron.Delims{Left: "[[", Right: "]]"},
155201
}))
156-
157-
sc.m.Use(middleware.GetContextHandler(nil, nil, nil))
202+
sc.m.Use(getContextHandler(t).Middleware)
158203

159204
return sc
160205
}
206+
207+
type fakeRenderService struct {
208+
rendering.Service
209+
}
210+
211+
func (s *fakeRenderService) Init() error {
212+
return nil
213+
}

pkg/api/frontendsettings.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,11 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
193193
"datasources": dataSources,
194194
"minRefreshInterval": setting.MinRefreshInterval,
195195
"panels": panels,
196-
"appUrl": setting.AppUrl,
197-
"appSubUrl": setting.AppSubUrl,
196+
"appUrl": hs.Cfg.AppURL,
197+
"appSubUrl": hs.Cfg.AppSubURL,
198198
"allowOrgCreate": (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
199199
"authProxyEnabled": setting.AuthProxyEnabled,
200-
"ldapEnabled": setting.LDAPEnabled,
200+
"ldapEnabled": hs.Cfg.LDAPEnabled,
201201
"alertingEnabled": setting.AlertingEnabled,
202202
"alertingErrorOrTimeout": setting.AlertingErrorOrTimeout,
203203
"alertingNoDataOrNullValues": setting.AlertingNoDataOrNullValues,

pkg/api/frontendsettings_test.go

+17-13
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/grafana/grafana/pkg/bus"
1919
"github.com/grafana/grafana/pkg/services/sqlstore"
2020

21-
"github.com/grafana/grafana/pkg/middleware"
2221
"gopkg.in/macaron.v1"
2322

2423
"github.com/grafana/grafana/pkg/setting"
@@ -53,7 +52,7 @@ func setupTestEnvironment(t *testing.T, cfg *setting.Cfg) (*macaron.Macaron, *HT
5352
}
5453

5554
m := macaron.New()
56-
m.Use(middleware.GetContextHandler(nil, nil, nil))
55+
m.Use(getContextHandler(t).Middleware)
5756
m.Use(macaron.Renderer(macaron.RenderOptions{
5857
Directory: filepath.Join(setting.StaticRootPath, "views"),
5958
IndentJSON: true,
@@ -84,10 +83,12 @@ func TestHTTPServer_GetFrontendSettings_hideVersionAnonyomus(t *testing.T) {
8483
setting.Env = "testing"
8584

8685
tests := []struct {
86+
desc string
8787
hideVersion bool
8888
expected settings
8989
}{
9090
{
91+
desc: "Not hiding version",
9192
hideVersion: false,
9293
expected: settings{
9394
BuildInfo: buildInfo{
@@ -98,6 +99,7 @@ func TestHTTPServer_GetFrontendSettings_hideVersionAnonyomus(t *testing.T) {
9899
},
99100
},
100101
{
102+
desc: "Hiding version",
101103
hideVersion: true,
102104
expected: settings{
103105
BuildInfo: buildInfo{
@@ -110,16 +112,18 @@ func TestHTTPServer_GetFrontendSettings_hideVersionAnonyomus(t *testing.T) {
110112
}
111113

112114
for _, test := range tests {
113-
hs.Cfg.AnonymousHideVersion = test.hideVersion
114-
expected := test.expected
115-
116-
recorder := httptest.NewRecorder()
117-
m.ServeHTTP(recorder, req)
118-
got := settings{}
119-
err := json.Unmarshal(recorder.Body.Bytes(), &got)
120-
require.NoError(t, err)
121-
require.GreaterOrEqual(t, 400, recorder.Code, "status codes higher than 400 indicates a failure")
122-
123-
assert.EqualValues(t, expected, got)
115+
t.Run(test.desc, func(t *testing.T) {
116+
hs.Cfg.AnonymousHideVersion = test.hideVersion
117+
expected := test.expected
118+
119+
recorder := httptest.NewRecorder()
120+
m.ServeHTTP(recorder, req)
121+
got := settings{}
122+
err := json.Unmarshal(recorder.Body.Bytes(), &got)
123+
require.NoError(t, err)
124+
require.GreaterOrEqual(t, 400, recorder.Code, "status codes higher than 400 indicate a failure")
125+
126+
assert.EqualValues(t, expected, got)
127+
})
124128
}
125129
}

pkg/api/http_server.go

+19-21
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/grafana/grafana/pkg/models"
3030
"github.com/grafana/grafana/pkg/plugins"
3131
"github.com/grafana/grafana/pkg/registry"
32+
"github.com/grafana/grafana/pkg/services/contexthandler"
3233
"github.com/grafana/grafana/pkg/services/datasources"
3334
"github.com/grafana/grafana/pkg/services/hooks"
3435
"github.com/grafana/grafana/pkg/services/login"
@@ -75,6 +76,7 @@ type HTTPServer struct {
7576
SearchService *search.SearchService `inject:""`
7677
ShortURLService *shorturls.ShortURLService `inject:""`
7778
Live *live.GrafanaLive `inject:""`
79+
ContextHandler *contexthandler.ContextHandler `inject:""`
7880
Listener net.Listener
7981
}
8082

@@ -100,7 +102,7 @@ func (hs *HTTPServer) Run(ctx context.Context) error {
100102
Addr: net.JoinHostPort(setting.HttpAddr, setting.HttpPort),
101103
Handler: hs.macaron,
102104
}
103-
switch setting.Protocol {
105+
switch hs.Cfg.Protocol {
104106
case setting.HTTP2Scheme:
105107
if err := hs.configureHttp2(); err != nil {
106108
return err
@@ -118,7 +120,7 @@ func (hs *HTTPServer) Run(ctx context.Context) error {
118120
}
119121

120122
hs.log.Info("HTTP Server Listen", "address", listener.Addr().String(), "protocol",
121-
setting.Protocol, "subUrl", setting.AppSubUrl, "socket", setting.SocketPath)
123+
hs.Cfg.Protocol, "subUrl", hs.Cfg.AppSubURL, "socket", hs.Cfg.SocketPath)
122124

123125
var wg sync.WaitGroup
124126
wg.Add(1)
@@ -133,7 +135,7 @@ func (hs *HTTPServer) Run(ctx context.Context) error {
133135
}
134136
}()
135137

136-
switch setting.Protocol {
138+
switch hs.Cfg.Protocol {
137139
case setting.HTTPScheme, setting.SocketScheme:
138140
if err := hs.httpSrv.Serve(listener); err != nil {
139141
if errors.Is(err, http.ErrServerClosed) {
@@ -151,7 +153,7 @@ func (hs *HTTPServer) Run(ctx context.Context) error {
151153
return err
152154
}
153155
default:
154-
panic(fmt.Sprintf("Unhandled protocol %q", setting.Protocol))
156+
panic(fmt.Sprintf("Unhandled protocol %q", hs.Cfg.Protocol))
155157
}
156158

157159
wg.Wait()
@@ -164,29 +166,29 @@ func (hs *HTTPServer) getListener() (net.Listener, error) {
164166
return hs.Listener, nil
165167
}
166168

167-
switch setting.Protocol {
169+
switch hs.Cfg.Protocol {
168170
case setting.HTTPScheme, setting.HTTPSScheme, setting.HTTP2Scheme:
169171
listener, err := net.Listen("tcp", hs.httpSrv.Addr)
170172
if err != nil {
171173
return nil, errutil.Wrapf(err, "failed to open listener on address %s", hs.httpSrv.Addr)
172174
}
173175
return listener, nil
174176
case setting.SocketScheme:
175-
listener, err := net.ListenUnix("unix", &net.UnixAddr{Name: setting.SocketPath, Net: "unix"})
177+
listener, err := net.ListenUnix("unix", &net.UnixAddr{Name: hs.Cfg.SocketPath, Net: "unix"})
176178
if err != nil {
177-
return nil, errutil.Wrapf(err, "failed to open listener for socket %s", setting.SocketPath)
179+
return nil, errutil.Wrapf(err, "failed to open listener for socket %s", hs.Cfg.SocketPath)
178180
}
179181

180182
// Make socket writable by group
181183
// nolint:gosec
182-
if err := os.Chmod(setting.SocketPath, 0660); err != nil {
184+
if err := os.Chmod(hs.Cfg.SocketPath, 0660); err != nil {
183185
return nil, errutil.Wrapf(err, "failed to change socket permissions")
184186
}
185187

186188
return listener, nil
187189
default:
188-
hs.log.Error("Invalid protocol", "protocol", setting.Protocol)
189-
return nil, fmt.Errorf("invalid protocol %q", setting.Protocol)
190+
hs.log.Error("Invalid protocol", "protocol", hs.Cfg.Protocol)
191+
return nil, fmt.Errorf("invalid protocol %q", hs.Cfg.Protocol)
190192
}
191193
}
192194

@@ -271,7 +273,7 @@ func (hs *HTTPServer) configureHttp2() error {
271273
}
272274

273275
func (hs *HTTPServer) newMacaron() *macaron.Macaron {
274-
macaron.Env = setting.Env
276+
macaron.Env = hs.Cfg.Env
275277
m := macaron.New()
276278

277279
// automatically set HEAD for every GET
@@ -294,13 +296,13 @@ func (hs *HTTPServer) applyRoutes() {
294296
func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
295297
m := hs.macaron
296298

297-
m.Use(middleware.Logger())
299+
m.Use(middleware.Logger(hs.Cfg))
298300

299301
if setting.EnableGzip {
300302
m.Use(middleware.Gziper())
301303
}
302304

303-
m.Use(middleware.Recovery())
305+
m.Use(middleware.Recovery(hs.Cfg))
304306

305307
for _, route := range plugins.StaticRoutes {
306308
pluginRoute := path.Join("/public/plugins/", route.PluginId)
@@ -316,7 +318,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
316318
hs.mapStatic(m, hs.Cfg.ImagesDir, "", "/public/img/attachments")
317319
}
318320

319-
m.Use(middleware.AddDefaultResponseHeaders())
321+
m.Use(middleware.AddDefaultResponseHeaders(hs.Cfg))
320322

321323
if setting.ServeFromSubPath && setting.AppSubUrl != "" {
322324
m.SetURLPrefix(setting.AppSubUrl)
@@ -334,16 +336,12 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
334336
m.Use(hs.apiHealthHandler)
335337
m.Use(hs.metricsEndpoint)
336338

337-
m.Use(middleware.GetContextHandler(
338-
hs.AuthTokenService,
339-
hs.RemoteCacheService,
340-
hs.RenderService,
341-
))
339+
m.Use(hs.ContextHandler.Middleware)
342340
m.Use(middleware.OrgRedirect())
343341

344342
// needs to be after context handler
345343
if setting.EnforceDomain {
346-
m.Use(middleware.ValidateHostHeader(setting.Domain))
344+
m.Use(middleware.ValidateHostHeader(hs.Cfg.Domain))
347345
}
348346

349347
m.Use(middleware.HandleNoCacheHeader())
@@ -433,7 +431,7 @@ func (hs *HTTPServer) mapStatic(m *macaron.Macaron, rootDir string, dir string,
433431
}
434432
}
435433

436-
if setting.Env == setting.Dev {
434+
if hs.Cfg.Env == setting.Dev {
437435
headers = func(c *macaron.Context) {
438436
c.Resp.Header().Set("Cache-Control", "max-age=0, must-revalidate, no-cache")
439437
}

pkg/api/index.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ func (hs *HTTPServer) getNavTree(c *models.ReqContext, hasEditPerm bool) ([]*dto
300300
{Text: "Stats", Id: "server-stats", Url: setting.AppSubUrl + "/admin/stats", Icon: "graph-bar"},
301301
}
302302

303-
if setting.LDAPEnabled {
303+
if hs.Cfg.LDAPEnabled {
304304
adminNavLinks = append(adminNavLinks, &dtos.NavLink{
305305
Text: "LDAP", Id: "ldap", Url: setting.AppSubUrl + "/admin/ldap", Icon: "book",
306306
})
@@ -371,7 +371,7 @@ func (hs *HTTPServer) setIndexViewData(c *models.ReqContext) (*dtos.IndexViewDat
371371

372372
// special case when doing localhost call from image renderer
373373
if c.IsRenderCall && !hs.Cfg.ServeFromSubPath {
374-
appURL = fmt.Sprintf("%s://localhost:%s", setting.Protocol, setting.HttpPort)
374+
appURL = fmt.Sprintf("%s://localhost:%s", hs.Cfg.Protocol, setting.HttpPort)
375375
appSubURL = ""
376376
settings["appSubUrl"] = ""
377377
}

0 commit comments

Comments
 (0)