mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ServeFromSubPath: Redirect to URL with subpath when subpath missing (#66724)
* ServeFromSubPath: Redirect to URL with subpath when subpath missing * Review fixes * Added tests * Use constant * change to useMiddleware * Update pkg/middleware/subpath_redirect.go --------- Co-authored-by: Carl Bergquist <carl.bergquist@gmail.com>
This commit is contained in:
parent
2767d5b1c2
commit
57701fd2f2
@ -602,6 +602,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
|
|||||||
|
|
||||||
if hs.Cfg.ServeFromSubPath && hs.Cfg.AppSubURL != "" {
|
if hs.Cfg.ServeFromSubPath && hs.Cfg.AppSubURL != "" {
|
||||||
m.SetURLPrefix(hs.Cfg.AppSubURL)
|
m.SetURLPrefix(hs.Cfg.AppSubURL)
|
||||||
|
m.UseMiddleware(middleware.SubPathRedirect(hs.Cfg))
|
||||||
}
|
}
|
||||||
|
|
||||||
m.UseMiddleware(web.Renderer(filepath.Join(hs.Cfg.StaticRootPath, "views"), "[[", "]]"))
|
m.UseMiddleware(web.Renderer(filepath.Join(hs.Cfg.StaticRootPath, "views"), "[[", "]]"))
|
||||||
@ -616,6 +617,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
|
|||||||
|
|
||||||
m.UseMiddleware(hs.ContextHandler.Middleware)
|
m.UseMiddleware(hs.ContextHandler.Middleware)
|
||||||
m.Use(middleware.OrgRedirect(hs.Cfg, hs.userService))
|
m.Use(middleware.OrgRedirect(hs.Cfg, hs.userService))
|
||||||
|
|
||||||
if !hs.Features.IsEnabled(featuremgmt.FlagAuthnService) {
|
if !hs.Features.IsEnabled(featuremgmt.FlagAuthnService) {
|
||||||
m.Use(accesscontrol.LoadPermissionsMiddleware(hs.accesscontrolService))
|
m.Use(accesscontrol.LoadPermissionsMiddleware(hs.accesscontrolService))
|
||||||
}
|
}
|
||||||
|
26
pkg/middleware/subpath_redirect.go
Normal file
26
pkg/middleware/subpath_redirect.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
|
"github.com/grafana/grafana/pkg/web"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SubPathRedirect Redirects URLs that are missing the configured subpath to an URL that contains the subpath.
|
||||||
|
func SubPathRedirect(cfg *setting.Cfg) web.Middleware {
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
// Direct to url with subpath if the request is missing the subpath and is not an API request.
|
||||||
|
if !strings.HasPrefix(req.RequestURI, cfg.AppSubURL) && !strings.HasPrefix(req.RequestURI, "/api") {
|
||||||
|
newURL := fmt.Sprintf("%s%s", cfg.AppURL, strings.TrimPrefix(req.RequestURI, "/"))
|
||||||
|
http.Redirect(rw, req, newURL, http.StatusMovedPermanently)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
next.ServeHTTP(rw, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
43
pkg/middleware/subpath_redirect_test.go
Normal file
43
pkg/middleware/subpath_redirect_test.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSubPathRedirect(t *testing.T) {
|
||||||
|
testSubPathRedirect(t, "/", "http://localhost:3000/subpath/")
|
||||||
|
testSubPathRedirect(t, "/admin/my/page", "http://localhost:3000/subpath/admin/my/page")
|
||||||
|
testSubPathRedirect(t, "/api/users", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSubPathRedirect(t *testing.T, url string, expectedRedirect string) {
|
||||||
|
middlewareScenario(t, "GET url without subpath", func(t *testing.T, sc *scenarioContext) {
|
||||||
|
sc.cfg.AppSubURL = "/subpath"
|
||||||
|
sc.cfg.AppURL = "http://localhost:3000/subpath/"
|
||||||
|
|
||||||
|
sc.m.UseMiddleware(SubPathRedirect(sc.cfg))
|
||||||
|
sc.m.Get("/api/users", sc.defaultHandler)
|
||||||
|
|
||||||
|
sc.fakeReqWithParams("GET", url, map[string]string{}).exec()
|
||||||
|
|
||||||
|
if expectedRedirect != "" {
|
||||||
|
assert.Equal(t, 301, sc.resp.Code)
|
||||||
|
|
||||||
|
// nolint:bodyclose
|
||||||
|
resp := sc.resp.Result()
|
||||||
|
t.Cleanup(func() {
|
||||||
|
err := resp.Body.Close()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
redirectURL, err := resp.Location()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, expectedRedirect, redirectURL.String())
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, 200, sc.resp.Code)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -99,7 +99,10 @@ func (sc *scenarioContext) fakeReqWithParams(method, url string, queryParams map
|
|||||||
for k, v := range queryParams {
|
for k, v := range queryParams {
|
||||||
q.Add(k, v)
|
q.Add(k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.URL.RawQuery = q.Encode()
|
req.URL.RawQuery = q.Encode()
|
||||||
|
req.RequestURI = req.URL.RequestURI()
|
||||||
|
|
||||||
require.NoError(sc.t, err)
|
require.NoError(sc.t, err)
|
||||||
|
|
||||||
reqCtx := &contextmodel.ReqContext{
|
reqCtx := &contextmodel.ReqContext{
|
||||||
|
Loading…
Reference in New Issue
Block a user