diff --git a/src/index.ts b/src/index.ts index dbe4190..5dcfd25 100644 --- a/src/index.ts +++ b/src/index.ts @@ -628,6 +628,19 @@ app.get("/openapi.json", (req, res) => { res.json(openApiDocument(resolveBasePath(req))); }); +// swagger-ui-express's static handler redirects /docs -> absolute "/docs/", which behind the +// AppFactory handle_path proxy drops the /apps/ prefix and breaks the page. Intercept +// the no-slash form first and redirect to the ROOT_PATH-prefixed URL (mirrors idoklad's +// UsePathBase), so the trailing-slash form keeps the public prefix. +app.get("/docs", (req, res, next) => { + // Express non-strict routing matches both /docs and /docs/ here; only the no-slash form + // needs the redirect (otherwise /docs/ would redirect to itself in a loop). + if (req.path.endsWith("/")) { + return next(); + } + res.redirect(301, `${resolveBasePath(req)}/docs/`); +}); + app.use("/docs", swaggerUi.serve, swaggerUi.setup(undefined, swaggerUiOptions())); addResourceEndpoints();