diff --git a/cmd/console/server.go b/cmd/console/server.go index 21bb5b64bc..59a5026dd4 100644 --- a/cmd/console/server.go +++ b/cmd/console/server.go @@ -98,6 +98,10 @@ func buildServer() (*restapi.Server, error) { return nil, err } + subPath := restapi.GetSubPath() + swaggerSpec.Spec().BasePath = subPath + swaggerSpec.Spec().BasePath + swaggerSpec.OrigSpec().BasePath = subPath + swaggerSpec.OrigSpec().BasePath + api := operations.NewConsoleAPI(swaggerSpec) api.Logger = restapi.LogInfo server := restapi.NewServer(api) diff --git a/restapi/configure_console.go b/restapi/configure_console.go index 0b7e077347..ffc79f2b26 100644 --- a/restapi/configure_console.go +++ b/restapi/configure_console.go @@ -319,17 +319,18 @@ func AuthenticationMiddleware(next http.Handler) http.Handler { func FileServerMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Server", globalAppName) // do not add version information + basePath := GetSubPath() switch { - case strings.HasPrefix(r.URL.Path, "/ws"): + case strings.HasPrefix(r.URL.Path, basePath+"ws"): serveWS(w, r) - case strings.HasPrefix(r.URL.Path, "/api"): + case strings.HasPrefix(r.URL.Path, basePath+"api"): next.ServeHTTP(w, r) default: buildFs, err := fs.Sub(portal_ui.GetStaticAssets(), "build") if err != nil { panic(err) } - wrapHandlerSinglePageApplication(requestBounce(http.FileServer(http.FS(buildFs)))).ServeHTTP(w, r) + wrapHandlerSinglePageApplication(requestBounce(http.StripPrefix(basePath, http.FileServer(http.FS(buildFs))))).ServeHTTP(w, r) } }) } @@ -355,7 +356,7 @@ func (w *notFoundRedirectRespWr) Write(p []byte) (int, error) { // handleSPA handles the serving of the React Single Page Application func handleSPA(w http.ResponseWriter, r *http.Request) { - basePath := "/" + basePath := GetSubPath() // For SPA mode we will replace root base with a sub path if configured unless we received cp=y and cpb=/NEW/BASE if v := r.URL.Query().Get("cp"); v == "y" { if base := r.URL.Query().Get("cpb"); base != "" { @@ -420,11 +421,11 @@ func handleSPA(w http.ResponseWriter, r *http.Request) { } // if we have a seeded basePath. This should override CONSOLE_SUBPATH every time, thus the `if else` - if basePath != "/" { + if basePath != GetSubPath() { indexPageBytes = replaceBaseInIndex(indexPageBytes, basePath) // if we have a custom subpath replace it in - } else if getSubPath() != "/" { - indexPageBytes = replaceBaseInIndex(indexPageBytes, getSubPath()) + } else if GetSubPath() != "/" { + indexPageBytes = replaceBaseInIndex(indexPageBytes, GetSubPath()) } indexPageBytes = replaceLicense(indexPageBytes) @@ -441,7 +442,7 @@ func handleSPA(w http.ResponseWriter, r *http.Request) { // wrapHandlerSinglePageApplication handles a http.FileServer returning a 404 and overrides it with index.html func wrapHandlerSinglePageApplication(h http.Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path == "/" { + if match, _ := regexp.MatchString(fmt.Sprintf("^%s/?$", GetSubPath()), r.URL.Path); match { handleSPA(w, r) return } @@ -470,7 +471,7 @@ func configureServer(s *http.Server, _, _ string) { s.ErrorLog = log.New(&nullWriter{}, "", 0) } -func getSubPath() string { +func GetSubPath() string { subPathOnce.Do(func() { cfgSubPath = parseSubPath(env.Get(SubPath, "")) }) diff --git a/restapi/configure_console_test.go b/restapi/configure_console_test.go index 07f897d2ca..cfdf7cc30d 100644 --- a/restapi/configure_console_test.go +++ b/restapi/configure_console_test.go @@ -76,7 +76,7 @@ func Test_parseSubPath(t *testing.T) { } } -func Test_getSubPath(t *testing.T) { +func Test_GetSubPath(t *testing.T) { type args struct { envValue string } @@ -104,14 +104,14 @@ func Test_getSubPath(t *testing.T) { args: args{ envValue: "/subpath/", }, - want: "/subpath/", + want: "/subpath", }, { name: "No starting slash", args: args{ envValue: "subpath/", }, - want: "/subpath/", + want: "/subpath", }, } for _, tt := range tests { @@ -119,7 +119,7 @@ func Test_getSubPath(t *testing.T) { t.Setenv(SubPath, tt.args.envValue) defer os.Unsetenv(SubPath) subPathOnce = sync.Once{} - assert.Equalf(t, tt.want, getSubPath(), "getSubPath()") + assert.Equalf(t, tt.want, GetSubPath(), "GetSubPath()") }) } } diff --git a/restapi/ws_handle.go b/restapi/ws_handle.go index 6d8b890bed..e6aab8c63f 100644 --- a/restapi/ws_handle.go +++ b/restapi/ws_handle.go @@ -44,7 +44,7 @@ var upgrader = websocket.Upgrader{ const ( // websocket base path - wsBasePath = "/ws" + wsBasePath = "ws" ) // ConsoleWebsocketAdmin interface of a Websocket Client @@ -151,7 +151,7 @@ func (c wsConn) remoteAddress() string { // Request should come like ws://:/ws/ func serveWS(w http.ResponseWriter, req *http.Request) { ctx := req.Context() - wsPath := strings.TrimPrefix(req.URL.Path, wsBasePath) + wsPath := strings.TrimPrefix(req.URL.Path, GetSubPath()+wsBasePath) // Perform authentication before upgrading to a Websocket Connection // authenticate WS connection with Console session, err := auth.GetClaimsFromTokenInRequest(req)