UNPKG

@fastify/express

Version:

Express compatibility layer for Fastify

460 lines (362 loc) 11.6 kB
'use strict' // Original Fastify test/middlewares.test.js file const { test } = require('node:test') const fastify = require('fastify') const fp = require('fastify-plugin') const cors = require('cors') const express = require('express') const helmet = require('helmet') const expressPlugin = require('../index') test('use a middleware', async t => { t.plan(5) const instance = fastify() t.after(() => instance.close()) instance.register(expressPlugin) .after(() => { const useRes = instance.use(function (_req, _res, next) { t.assert.ok('middleware called') next() }) t.assert.deepStrictEqual(useRes, instance) }) instance.get('/', function (_request, reply) { reply.send({ hello: 'world' }) }) const address = await instance.listen({ port: 0 }) const result = await fetch(address) const responseText = await result.text() t.assert.deepStrictEqual(result.status, 200) t.assert.deepStrictEqual(result.headers.get('content-length'), '' + responseText.length) t.assert.deepStrictEqual(JSON.parse(responseText), { hello: 'world' }) }) test('use cors', async t => { t.plan(1) const instance = fastify() t.after(() => instance.close()) instance.register(expressPlugin) .after(() => { instance.use(cors()) }) instance.get('/', function (_request, reply) { reply.send({ hello: 'world' }) }) const address = await instance.listen({ port: 0 }) const result = await fetch(address) t.assert.deepStrictEqual(result.headers.get('access-control-allow-origin'), '*') }) test('use helmet', async t => { t.plan(1) const instance = fastify() t.after(() => instance.close()) instance.register(expressPlugin) .after(() => { instance.use(helmet()) }) instance.get('/', function (_request, reply) { reply.send({ hello: 'world' }) }) const address = await instance.listen({ port: 0 }) const result = await fetch(address) t.assert.ok(result.headers.get('x-xss-protection')) }) test('use helmet and cors', async t => { t.plan(2) const instance = fastify() t.after(() => instance.close()) instance.register(expressPlugin) .after(() => { instance.use(cors()) instance.use(helmet()) }) instance.get('/', function (_request, reply) { reply.send({ hello: 'world' }) }) const address = await instance.listen({ port: 0 }) const result = await fetch(address) t.assert.ok(result.headers.get('x-xss-protection')) t.assert.deepStrictEqual(result.headers.get('access-control-allow-origin'), '*') }) test('use cors only on prefix', async t => { t.plan(1) const instance = fastify() t.after(() => instance.close()) instance.register((innerInstance) => { innerInstance.register(expressPlugin).after(() => { innerInstance.use('/', cors()) }) innerInstance.get('/', function (_request, reply) { reply.send({ hello: 'world' }) }) }, { prefix: '/prefix' }) const address = await instance.listen({ port: 0 }) const result = await fetch(address + '/prefix') t.assert.deepStrictEqual(result.headers.get('access-control-allow-origin'), '*') }) test('middlewares with prefix', async t => { t.plan(4) const instance = fastify() t.after(() => instance.close()) instance.register(expressPlugin) .after(() => { instance.use(function (req, _res, next) { req.global = true next() }) instance.use('', function (req, _res, next) { req.global2 = true next() }) instance.use('/', function (req, _res, next) { req.root = true next() }) instance.use('/prefix', function (req, _res, next) { req.prefixed = true next() }) instance.use('/prefix/', function (req, _res, next) { req.slashed = true next() }) }) function handler (request, reply) { reply.send({ prefixed: request.raw.prefixed, slashed: request.raw.slashed, global: request.raw.global, global2: request.raw.global2, root: request.raw.root }) } instance.get('/', handler) instance.get('/prefix', handler) instance.get('/prefix/', handler) instance.get('/prefix/inner', handler) const address = await instance.listen({ port: 0 }) await t.test('/', async t => { t.plan(1) const result = await fetch(address + '/') t.assert.deepStrictEqual(await result.json(), { global: true, global2: true, root: true }) }) await t.test('/prefix', async t => { t.plan(1) const result = await fetch(address + '/prefix') t.assert.deepStrictEqual(await result.json(), { prefixed: true, global: true, global2: true, root: true, slashed: true }) }) await t.test('/prefix/', async t => { t.plan(1) const result = await fetch(address + '/prefix/') t.assert.deepStrictEqual(await result.json(), { prefixed: true, slashed: true, global: true, global2: true, root: true }) }) await t.test('/prefix/inner', async t => { t.plan(1) const result = await fetch(address + '/prefix/inner') t.assert.deepStrictEqual(await result.json(), { prefixed: true, slashed: true, global: true, global2: true, root: true }) }) }) test('res.end should block middleware execution', async t => { t.plan(4) const instance = fastify() t.after(() => instance.close()) instance.register(expressPlugin) .after(() => { instance.use(function (_req, res) { res.send('hello') }) instance.use(function () { t.assert.fail('we should not be here') }) }) instance.addHook('onRequest', (_req, _res, next) => { t.assert.ok('called') next() }) instance.addHook('preHandler', () => { t.assert.fail('this should not be called') }) instance.addHook('onSend', (_req, _reply, payload, next) => { t.assert.ok('called') next(null, payload) }) instance.addHook('onResponse', (_request, _reply, next) => { t.assert.ok('called') next() }) instance.get('/', function () { t.assert.fail('we should no be here') }) const address = await instance.listen({ port: 0 }) const result = await fetch(address) t.assert.deepStrictEqual(result.status, 200) t.assert.deepStrictEqual(await result.text(), 'hello') }) test('Use a middleware inside a plugin after an encapsulated plugin', async t => { t.plan(3) const f = fastify() t.after(() => f.close()) f.register(expressPlugin) f.register(function (instance, _opts, next) { instance.use(function (_req, _res, next) { t.assert.ok('first middleware called') next() }) instance.get('/', function (_request, reply) { reply.send({ hello: 'world' }) }) next() }) f.register(fp(function (instance, _opts, next) { instance.use(function (_req, _res, next) { t.assert.ok('second middleware called') next() }) next() })) const address = await f.listen({ port: 0 }) const result = await fetch(address) t.assert.deepStrictEqual(result.status, 200) t.assert.deepStrictEqual(await result.json(), { hello: 'world' }) }) test('middlewares should run in the order in which they are defined', async t => { t.plan(8) const f = fastify() t.after(() => f.close()) f.register(expressPlugin) f.register(fp(function (instance, _opts, next) { instance.use(function (req, _res, next) { t.assert.deepStrictEqual(req.previous, undefined) req.previous = 1 next() }) instance.register(fp(function (i, _opts, next) { i.use(function (req, _res, next) { t.assert.deepStrictEqual(req.previous, 2) req.previous = 3 next() }) next() })) instance.use(function (req, _res, next) { t.assert.deepStrictEqual(req.previous, 1) req.previous = 2 next() }) next() })) f.register(function (instance, _opts, next) { instance.use(function (req, _res, next) { t.assert.deepStrictEqual(req.previous, 3) req.previous = 4 next() }) instance.get('/', function (request, reply) { t.assert.deepStrictEqual(request.raw.previous, 5) reply.send({ hello: 'world' }) }) instance.register(fp(function (i, _opts, next) { i.use(function (req, _res, next) { t.assert.deepStrictEqual(req.previous, 4) req.previous = 5 next() }) next() })) next() }) const address = await f.listen({ port: 0 }) const result = await fetch(address) t.assert.deepStrictEqual(result.status, 200) t.assert.deepStrictEqual(await result.json(), { hello: 'world' }) }) test('middlewares for encoded paths', async t => { await t.test('decode the request url and run the middleware', async (t) => { await checkEncodedPath('/encoded', '/%65ncoded', t) }) await t.test('does not double decode the url', async (t) => { await checkEncodedPath('/%65ncoded', '/%2565ncoded', t) }) await t.test('handle the decoding for express handlers', async (t) => { t.plan(6) const routeUrl = '/express' const requestUrl = '/%65xpress' const instance = fastify() t.after(() => instance.close()) instance.addHook('onSend', async function hook (request, reply, payload) { t.assert.deepStrictEqual(request.raw.url, routeUrl) t.assert.deepStrictEqual(request.raw.originalUrl, requestUrl) return payload }) instance.addHook('onResponse', async function hook (request, reply) { t.assert.deepStrictEqual(request.raw.url, routeUrl) t.assert.deepStrictEqual(request.raw.originalUrl, requestUrl) }) await instance.register(expressPlugin) // Register the express-like middleware instance.use(routeUrl, function (req, _res, next) { req.slashedByExpress = true next() }) // Register an express Router with an express handler const innerRouter = express.Router() innerRouter.get(routeUrl, function (req, res) { res.send({ slashedByExpress: req.slashedByExpress }) }) instance.use(innerRouter) const address = await instance.listen({ port: 0 }) const response = await fetch(address + requestUrl) const body = await response.json() t.assert.ok(response.ok) t.assert.deepStrictEqual(body, { slashedByExpress: true }) }) }) async function checkEncodedPath (routeUrl, requestUrl, t) { t.plan(6) const instance = fastify() t.after(() => instance.close()) instance.addHook('onSend', async function hook (request, reply, payload) { t.assert.deepStrictEqual(request.raw.url, routeUrl) t.assert.deepStrictEqual(request.raw.originalUrl, requestUrl) return payload }) instance.addHook('onResponse', async function hook (request, reply) { t.assert.deepStrictEqual(request.raw.url, routeUrl) t.assert.deepStrictEqual(request.raw.originalUrl, requestUrl) }) await instance.register(expressPlugin) // Register the express-like middleware instance.use(routeUrl, function (req, _res, next) { req.slashed = true next() }) // ... with a Fastify route handler instance.get(routeUrl, (request, reply) => { reply.send({ slashed: request.raw.slashed, }) }) const address = await instance.listen({ port: 0 }) const response = await fetch(address + requestUrl) const body = await response.json() t.assert.ok(response.ok) t.assert.deepStrictEqual(body, { slashed: true }) }