Skip to content
Snippets Groups Projects
Commit 16905598 authored by richard.petersen's avatar richard.petersen :sailboat:
Browse files

Fix: UI-Middleware responds with a 404 when the trailing slash is not found

Root cause: Express automatically redirected, fastify does not
Solution: Manually do the redirect
parent f9a5bc7a
No related branches found
No related tags found
No related merge requests found
import request from 'supertest'
import { generateSimpleViteManifest, mockApp, mockConfig, mockFetch, mockRedis } from './util.js'
import { expect } from 'chai'
import * as td from 'testdouble'
import RedisMock from 'ioredis-mock'
describe('With different app root', function () {
let app
beforeEach(async function () {
let count = 0
mockConfig({ urls: ['http://ui-server/'] })
mockRedis()
mockFetch({
'http://ui-server': {
'/manifest.json': generateSimpleViteManifest({
'example.js': { imports: ['test.txt'] },
'test.txt': { },
'main.css': {},
'index.html': {
file: 'index.html.js',
isEntry: true,
imports: ['example.js'],
css: ['main.css']
},
'image.png': {}
}),
'/example.js': () => new Response('this is example', { headers: { 'content-type': 'application/javascript' } }),
'/test.txt': () => new Response('this is test', { headers: { 'content-type': 'text/plain' } }),
'/index.html.js': () => new Response('this is index.html.js', { headers: { 'content-type': 'application/javascript' } }),
'/index.html': () => new Response('<html><head></head><body>it\'s me</body></html>', { headers: { 'content-type': 'text/html' } }),
'/main.css': () => new Response('.foo { color: #000; }', { headers: { 'content-type': 'text/css' } }),
'/favicon.ico': 'not really a favicon, though',
'/test.svg': () => {
if (count > 0) {
return new Response(null, { status: 404 })
}
count++
return new Response('<svg></svg>', { headers: { 'content-type': 'image/svg' } })
}
}
})
process.env.APP_ROOT = '/appsuite/'
app = await mockApp()
})
afterEach(async function () {
process.env.APP_ROOT = '/'
await new RedisMock().flushdb()
td.reset()
})
it('serves files defined in manifest.json file', async function () {
const response = await request(app.server).get('/appsuite/example.js')
expect(response.statusCode).to.equal(200)
expect(response.headers['content-type']).to.equal('application/javascript')
expect(response.text).to.equal('this is example')
const response2 = await request(app.server).get('/appsuite/test.txt')
expect(response2.statusCode).to.equal(200)
expect(response2.headers['content-type']).to.equal('text/plain')
expect(response2.text).to.equal('this is test')
})
it('serves / as index.html', async function () {
const response = await request(app.server).get('/appsuite/')
expect(response.statusCode).to.equal(200)
expect(response.headers['content-type']).to.equal('text/html')
expect(response.text).to.equal('<html><head></head><body>it\'s me</body></html>')
})
it('serves approot without slash as index.html', async function () {
const response = await request(app.server).get('/appsuite')
expect(response.statusCode).to.equal(302)
expect(response.headers.location).to.equal('/appsuite/')
})
it('directly fetches files not referenced in manifest.json files from the upstream servers', async function () {
const response = await request(app.server).get('/appsuite/favicon.ico')
expect(response.statusCode).to.equal(200)
expect(response.text).to.equal('not really a favicon, though')
})
it('returns 404 if a file misses the app-root', async function () {
const response = await request(app.server).get('/example.js')
expect(response.statusCode).to.equal(404)
})
})
......@@ -68,8 +68,13 @@ export async function createApp (basePath) {
await app.register(manifestsPlugin, { prefix: process.env.APP_ROOT })
await app.register(metadataPlugin, { prefix: process.env.APP_ROOT })
await app.register(redirectsPlugin, { prefix: process.env.APP_ROOT })
if (process.env.APP_ROOT.length > 1) {
app.get(process.env.APP_ROOT.slice(0, -1), async (req, res) => {
res.redirect(process.env.APP_ROOT)
})
}
await app.register(serveFilePlugin, { prefix: process.env.APP_ROOT })
await app.register(serveFilePlugin)
return app
}
......@@ -6,7 +6,8 @@ export default async function serveFilePlugin (fastify, options) {
fastify.get('*', async (req, reply) => {
try {
const version = reply.version
const url = req.urlData('path').substr((options.prefix || '/').length - 1)
const url = req.urlData('path').substr(process.env.APP_ROOT.length - 1)
const path = url === '/' ? '/index.html' : url
const { body, headers } = await getFile({ version, path })
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment