diff --git a/pkg/api/serve.go b/pkg/api/serve.go index 5bc7ffed954..c93ffea55db 100644 --- a/pkg/api/serve.go +++ b/pkg/api/serve.go @@ -33,6 +33,8 @@ const ( extensionValidationExcludeBody = "x-validation-exclude-body" ) +var ErrInvalidAPIEndpoint = errors.New("invalid API endpoint") + type responseError struct { Message string `json:"message"` } @@ -85,6 +87,7 @@ func Serve( r.Mount("/_pprof/", httputil.ServePPROF("/_pprof/")) r.Mount("/swagger.json", http.HandlerFunc(swaggerSpecHandler)) r.Mount("/", uiHandler) + r.Mount(BaseURL, http.HandlerFunc(InvalidAPIEndpointHandler)) return r } @@ -162,3 +165,10 @@ func validateRequest(r *http.Request, router routers.Router, options *openapi3fi } return http.StatusOK, nil } + +// InvalidAPIEndpointHandler returns ErrInvalidAPIEndpoint, and is currently being used to ensure +// that routes under the pattern it is used with in chi.Router.Mount (i.e. /api/v1) are +// not accessible. +func InvalidAPIEndpointHandler(w http.ResponseWriter, _ *http.Request) { + writeError(w, http.StatusInternalServerError, ErrInvalidAPIEndpoint) +} diff --git a/pkg/api/serve_test.go b/pkg/api/serve_test.go index ebd02b20b16..2ae91d5a3c2 100644 --- a/pkg/api/serve_test.go +++ b/pkg/api/serve_test.go @@ -178,3 +178,34 @@ func setupClientWithAdmin(t testing.TB, blockstoreType string, opts ...testutil. clt = setupClientByEndpoint(t, server.URL, cred.AccessKeyID, cred.SecretAccessKey) return clt, deps } + +func TestInvalidRoute(t *testing.T) { + handler, _ := setupHandler(t, "") + server := setupServer(t, handler) + clt := setupClientByEndpoint(t, server.URL, "", "") + cred := createDefaultAdminUser(t, clt) + + // setup client with invalid endpoint base url + basicAuthProvider, err := securityprovider.NewSecurityProviderBasicAuth(cred.AccessKeyID, cred.SecretAccessKey) + if err != nil { + t.Fatal("basic auth security provider", err) + } + clt, err = api.NewClientWithResponses(server.URL+api.BaseURL+"//", api.WithRequestEditorFn(basicAuthProvider.Intercept)) + if err != nil { + t.Fatal("failed to create api client:", err) + } + + ctx := context.Background() + resp, err := clt.ListRepositoriesWithResponse(ctx, &api.ListRepositoriesParams{}) + if err != nil { + t.Fatalf("failed to get lakefs server version") + } + if resp.JSONDefault == nil { + t.Fatalf("client api call expected default error, got nil") + } + expectedErrMsg := api.ErrInvalidAPIEndpoint.Error() + errMsg := resp.JSONDefault.Message + if errMsg != expectedErrMsg { + t.Fatalf("client response error message: %s, expected: %s", errMsg, expectedErrMsg) + } +}