diff --git a/lib/index-html.js b/lib/index-html.js
index 886872b..85cbc17 100644
--- a/lib/index-html.js
+++ b/lib/index-html.js
@@ -1,8 +1,10 @@
'use strict'
function indexHtml (opts) {
- return (hasTrailingSlash) => {
- const prefix = hasTrailingSlash ? `.${opts.staticPrefix}` : `${opts.prefix}${opts.staticPrefix}`
+ const hasLeadingSlash = /^\//.test(opts.prefix)
+ return (url) => {
+ const hasTrailingSlash = /\/$/.test(url)
+ const prefix = hasTrailingSlash ? `.${opts.staticPrefix}` : `${hasLeadingSlash ? '.' : ''}${opts.prefix}${opts.staticPrefix}`
return `
diff --git a/lib/routes.js b/lib/routes.js
index 3b206d5..f4be95f 100644
--- a/lib/routes.js
+++ b/lib/routes.js
@@ -112,10 +112,9 @@ 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(hasTrailingSlash)) // trailing slash alters the relative urls generated in the html
+ .send(indexHtmlContent(req.url)) // trailing slash alters the relative urls generated in the html
}
})
diff --git a/test/route.test.js b/test/route.test.js
index 86d9b31..17a56da 100644
--- a/test/route.test.js
+++ b/test/route.test.js
@@ -538,7 +538,7 @@ test('should return empty log level of route /documentation', async (t) => {
})
test('/documentation should display index html with correct asset urls', async (t) => {
- t.plan(4)
+ t.plan(6)
const fastify = Fastify()
await fastify.register(fastifySwagger, swaggerOption)
await fastify.register(fastifySwaggerUi, { theme: { js: [{ filename: 'theme-js.js' }] } })
@@ -548,10 +548,122 @@ 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)
+
+ let cssRes = await fastify.inject({
+ method: 'GET',
+ url: '/documentation/static/index.css'
+ })
+ t.equal(cssRes.statusCode, 200)
+ cssRes = await fastify.inject({
+ method: 'GET',
+ url: './documentation/static/index.css'
+ })
+ t.equal(cssRes.statusCode, 200)
+})
+
+/**
+ * This emulates when the server is inside an NGINX application that routes by path
+ */
+test('/documentation should display index html with correct asset urls when nested', async (t) => {
+ t.plan(5)
+ const fastify = Fastify()
+ await fastify.register(
+ async () => {
+ await fastify.register(fastifySwagger, swaggerOption)
+ await fastify.register(fastifySwaggerUi, { theme: { js: [{ filename: 'theme-js.js' }] } })
+ },
+ {
+ prefix: '/swagger-app'
+ }
+ )
+
+ const res = await fastify.inject({
+ method: 'GET',
+ url: '/swagger-app/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)
+
+ const cssRes = await fastify.inject({
+ method: 'GET',
+ url: '/swagger-app/documentation/static/index.css'
+ })
+ t.equal(cssRes.statusCode, 200)
+})
+
+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 with no leading slash', 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)
})
test('/documentation/ should display index html with correct asset urls', async (t) => {
@@ -582,10 +694,10 @@ test('/docs should display index html with correct asset urls when documentation
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)
+ 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) => {