From 8006c0554904dd84a0bbc8afc996525bffc58567 Mon Sep 17 00:00:00 2001 From: Jonathan Hollander Date: Fri, 19 Jul 2024 13:04:35 +0100 Subject: [PATCH] Relative urls for static content (#164) Fixes regression where relative urls for the static content became absolute, thus breaking reverse proxy usage. This commit reverts to relative urls for this content, taking into account whether the route that delivers them has a trailing slash or not. --- lib/index-html.js | 55 ++++++++++++++++++++++-------------------- lib/routes.js | 3 ++- test/route.test.js | 59 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 86 insertions(+), 31 deletions(-) diff --git a/lib/index-html.js b/lib/index-html.js index 2e83015..132b29a 100644 --- a/lib/index-html.js +++ b/lib/index-html.js @@ -1,32 +1,35 @@ 'use strict' function indexHtml (opts) { - return (url) => ` - - - - - ${opts.theme?.title || 'Swagger UI'} - - - ${opts.theme && opts.theme.css ? opts.theme.css.map(css => `\n`).join('') : ''} - ${opts.theme && opts.theme.favicon -? opts.theme.favicon.map(favicon => `\n`).join('') -: ` - - - `} - - - -
- - - - ${opts.theme && opts.theme.js ? opts.theme.js.map(js => `\n`).join('') : ''} - - - ` + return (hasTrailingSlash) => { + const prefix = hasTrailingSlash ? `.${opts.staticPrefix}` : `.${opts.prefix}${opts.staticPrefix}` + return ` + + + + + ${opts.theme?.title || 'Swagger UI'} + + + ${opts.theme && opts.theme.css ? opts.theme.css.map(css => `\n`).join('') : ''} + ${opts.theme && opts.theme.favicon + ? opts.theme.favicon.map(favicon => `\n`).join('') + : ` + + + `} + + + +
+ + + + ${opts.theme && opts.theme.js ? opts.theme.js.map(js => `\n`).join('') : ''} + + + ` + } } module.exports = indexHtml diff --git a/lib/routes.js b/lib/routes.js index bb6e4aa..3b206d5 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -112,9 +112,10 @@ function fastifySwagger (fastify, opts, done) { schema: { hide: true }, ...hooks, handler: (req, reply) => { + const hasTrailingSlash = /\/$/.test(req.url) reply .header('content-type', 'text/html; charset=utf-8') - .send(indexHtmlContent(req.url.replace(/\/$/, ''))) // remove trailing slash, as staticPrefix has a leading slash + .send(indexHtmlContent(hasTrailingSlash)) // trailing slash alters the relative urls generated in the html } }) diff --git a/test/route.test.js b/test/route.test.js index 03fd690..5664f36 100644 --- a/test/route.test.js +++ b/test/route.test.js @@ -548,8 +548,59 @@ test('/documentation should display index html with correct asset urls', async ( url: '/documentation' }) - t.equal(res.payload.includes('href="/documentation/static/index.css"'), true) - t.equal(res.payload.includes('src="/documentation/static/theme/theme-js.js"'), true) - t.equal(res.payload.includes('href="/documentation/index.css"'), false) - t.equal(res.payload.includes('src="/documentation/theme/theme-js.js"'), false) + t.equal(res.payload.includes('href="./documentation/static/index.css"'), true) + t.equal(res.payload.includes('src="./documentation/static/theme/theme-js.js"'), true) + t.equal(res.payload.includes('href="./documentation/index.css"'), false) + t.equal(res.payload.includes('src="./documentation/theme/theme-js.js"'), false) +}) + +test('/documentation/ should display index html with correct asset urls', async (t) => { + t.plan(4) + const fastify = Fastify() + await fastify.register(fastifySwagger, swaggerOption) + await fastify.register(fastifySwaggerUi, { theme: { js: [{ filename: 'theme-js.js' }] } }) + + const res = await fastify.inject({ + method: 'GET', + url: '/documentation/' + }) + + t.equal(res.payload.includes('href="./static/index.css"'), true) + t.equal(res.payload.includes('src="./static/theme/theme-js.js"'), true) + t.equal(res.payload.includes('href="./index.css"'), false) + t.equal(res.payload.includes('src="./theme/theme-js.js"'), false) +}) + +test('/docs should display index html with correct asset urls when documentation prefix is set', async (t) => { + t.plan(4) + const fastify = Fastify() + await fastify.register(fastifySwagger, swaggerOption) + await fastify.register(fastifySwaggerUi, { theme: { js: [{ filename: 'theme-js.js' }] }, routePrefix: '/docs' }) + + const res = await fastify.inject({ + method: 'GET', + url: '/docs' + }) + + t.equal(res.payload.includes('href="./docs/static/index.css"'), true) + t.equal(res.payload.includes('src="./docs/static/theme/theme-js.js"'), true) + t.equal(res.payload.includes('href="./docs/index.css"'), false) + t.equal(res.payload.includes('src="./docs/theme/theme-js.js"'), false) +}) + +test('/docs/ should display index html with correct asset urls when documentation prefix is set', async (t) => { + t.plan(4) + const fastify = Fastify() + await fastify.register(fastifySwagger, swaggerOption) + await fastify.register(fastifySwaggerUi, { theme: { js: [{ filename: 'theme-js.js' }] }, routePrefix: '/docs' }) + + const res = await fastify.inject({ + method: 'GET', + url: '/docs/' + }) + + t.equal(res.payload.includes('href="./static/index.css"'), true) + t.equal(res.payload.includes('src="./static/theme/theme-js.js"'), true) + t.equal(res.payload.includes('href="./index.css"'), false) + t.equal(res.payload.includes('src="./theme/theme-js.js"'), false) })