strong-tie/inbound-calls
0
1'use strict'2 3const split = require('split2')4const { test } = require('node:test')5const Fastify = require('../')6const {7 FST_ERR_BAD_URL,8 FST_ERR_ASYNC_CONSTRAINT9} = require('../lib/errors')10 11test('Should honor ignoreTrailingSlash option', async t => {12 t.plan(4)13 const fastify = Fastify({14 ignoreTrailingSlash: true15 })16 17 fastify.get('/test', (req, res) => {18 res.send('test')19 })20 21 let res = await fastify.inject('/test')22 t.assert.strictEqual(res.statusCode, 200)23 t.assert.strictEqual(res.payload.toString(), 'test')24 25 res = await fastify.inject('/test/')26 t.assert.strictEqual(res.statusCode, 200)27 t.assert.strictEqual(res.payload.toString(), 'test')28})29 30test('Should honor ignoreDuplicateSlashes option', async t => {31 t.plan(4)32 const fastify = Fastify({33 ignoreDuplicateSlashes: true34 })35 36 fastify.get('/test//test///test', (req, res) => {37 res.send('test')38 })39 40 let res = await fastify.inject('/test/test/test')41 t.assert.strictEqual(res.statusCode, 200)42 t.assert.strictEqual(res.payload.toString(), 'test')43 44 res = await fastify.inject('/test//test///test')45 t.assert.strictEqual(res.statusCode, 200)46 t.assert.strictEqual(res.payload.toString(), 'test')47})48 49test('Should honor ignoreTrailingSlash and ignoreDuplicateSlashes options', async t => {50 t.plan(4)51 const fastify = Fastify({52 ignoreTrailingSlash: true,53 ignoreDuplicateSlashes: true54 })55 56 fastify.get('/test//test///test', (req, res) => {57 res.send('test')58 })59 60 let res = await fastify.inject('/test/test/test/')61 t.assert.strictEqual(res.statusCode, 200)62 t.assert.strictEqual(res.payload.toString(), 'test')63 64 res = await fastify.inject('/test//test///test//')65 t.assert.strictEqual(res.statusCode, 200)66 t.assert.strictEqual(res.payload.toString(), 'test')67})68 69test('Should honor maxParamLength option', async (t) => {70 const fastify = Fastify({ maxParamLength: 10 })71 72 fastify.get('/test/:id', (req, reply) => {73 reply.send({ hello: 'world' })74 })75 76 const res = await fastify.inject({77 method: 'GET',78 url: '/test/123456789'79 })80 t.assert.strictEqual(res.statusCode, 200)81 82 const resError = await fastify.inject({83 method: 'GET',84 url: '/test/123456789abcd'85 })86 t.assert.strictEqual(resError.statusCode, 404)87})88 89test('Should expose router options via getters on request and reply', (t, done) => {90 t.plan(9)91 const fastify = Fastify()92 const expectedSchema = {93 params: {94 type: 'object',95 properties: {96 id: { type: 'integer' }97 }98 }99 }100 101 fastify.get('/test/:id', {102 schema: expectedSchema103 }, (req, reply) => {104 t.assert.strictEqual(reply.routeOptions.config.url, '/test/:id')105 t.assert.strictEqual(reply.routeOptions.config.method, 'GET')106 t.assert.deepStrictEqual(req.routeOptions.schema, expectedSchema)107 t.assert.strictEqual(typeof req.routeOptions.handler, 'function')108 t.assert.strictEqual(req.routeOptions.config.url, '/test/:id')109 t.assert.strictEqual(req.routeOptions.config.method, 'GET')110 t.assert.strictEqual(req.is404, false)111 reply.send({ hello: 'world' })112 })113 114 fastify.inject({115 method: 'GET',116 url: '/test/123456789'117 }, (error, res) => {118 t.assert.ifError(error)119 t.assert.strictEqual(res.statusCode, 200)120 done()121 })122})123 124test('Should set is404 flag for unmatched paths', (t, done) => {125 t.plan(3)126 const fastify = Fastify()127 128 fastify.setNotFoundHandler((req, reply) => {129 t.assert.strictEqual(req.is404, true)130 reply.code(404).send({ error: 'Not Found', message: 'Four oh for', statusCode: 404 })131 })132 133 fastify.inject({134 method: 'GET',135 url: '/nonexist/123456789'136 }, (error, res) => {137 t.assert.ifError(error)138 t.assert.strictEqual(res.statusCode, 404)139 done()140 })141})142 143test('Should honor frameworkErrors option - FST_ERR_BAD_URL', (t, done) => {144 t.plan(3)145 const fastify = Fastify({146 frameworkErrors: function (err, req, res) {147 if (err instanceof FST_ERR_BAD_URL) {148 t.assert.ok(true)149 } else {150 t.assert.fail()151 }152 res.send(`${err.message} - ${err.code}`)153 }154 })155 156 fastify.get('/test/:id', (req, res) => {157 res.send('{ hello: \'world\' }')158 })159 160 fastify.inject(161 {162 method: 'GET',163 url: '/test/%world'164 },165 (err, res) => {166 t.assert.ifError(err)167 t.assert.strictEqual(res.body, '\'/test/%world\' is not a valid url component - FST_ERR_BAD_URL')168 done()169 }170 )171})172 173test('Should supply Fastify request to the logger in frameworkErrors wrapper - FST_ERR_BAD_URL', (t, done) => {174 t.plan(8)175 176 const REQ_ID = 'REQ-1234'177 const logStream = split(JSON.parse)178 179 const fastify = Fastify({180 frameworkErrors: function (err, req, res) {181 t.assert.deepStrictEqual(req.id, REQ_ID)182 t.assert.deepStrictEqual(req.raw.httpVersion, '1.1')183 res.send(`${err.message} - ${err.code}`)184 },185 logger: {186 stream: logStream,187 serializers: {188 req (request) {189 t.assert.deepStrictEqual(request.id, REQ_ID)190 return { httpVersion: request.raw.httpVersion }191 }192 }193 },194 genReqId: () => REQ_ID195 })196 197 fastify.get('/test/:id', (req, res) => {198 res.send('{ hello: \'world\' }')199 })200 201 logStream.on('data', (json) => {202 t.assert.deepStrictEqual(json.msg, 'incoming request')203 t.assert.deepStrictEqual(json.reqId, REQ_ID)204 t.assert.deepStrictEqual(json.req.httpVersion, '1.1')205 })206 207 fastify.inject(208 {209 method: 'GET',210 url: '/test/%world'211 },212 (err, res) => {213 t.assert.ifError(err)214 t.assert.strictEqual(res.body, '\'/test/%world\' is not a valid url component - FST_ERR_BAD_URL')215 done()216 }217 )218})219 220test('Should honor disableRequestLogging option in frameworkErrors wrapper - FST_ERR_BAD_URL', (t, done) => {221 t.plan(2)222 223 const logStream = split(JSON.parse)224 225 const fastify = Fastify({226 disableRequestLogging: true,227 frameworkErrors: function (err, req, res) {228 res.send(`${err.message} - ${err.code}`)229 },230 logger: {231 stream: logStream,232 serializers: {233 req () {234 t.assert.fail('should not be called')235 },236 res () {237 t.assert.fail('should not be called')238 }239 }240 }241 })242 243 fastify.get('/test/:id', (req, res) => {244 res.send('{ hello: \'world\' }')245 })246 247 logStream.on('data', (json) => {248 t.assert.fail('should not be called')249 })250 251 fastify.inject(252 {253 method: 'GET',254 url: '/test/%world'255 },256 (err, res) => {257 t.assert.ifError(err)258 t.assert.strictEqual(res.body, '\'/test/%world\' is not a valid url component - FST_ERR_BAD_URL')259 done()260 }261 )262})263 264test('Should honor frameworkErrors option - FST_ERR_ASYNC_CONSTRAINT', (t, done) => {265 t.plan(3)266 267 const constraint = {268 name: 'secret',269 storage: function () {270 const secrets = {}271 return {272 get: (secret) => { return secrets[secret] || null },273 set: (secret, store) => { secrets[secret] = store }274 }275 },276 deriveConstraint: (req, ctx, done) => {277 done(Error('kaboom'))278 },279 validate () { return true }280 }281 282 const fastify = Fastify({283 frameworkErrors: function (err, req, res) {284 if (err instanceof FST_ERR_ASYNC_CONSTRAINT) {285 t.assert.ok(true)286 } else {287 t.assert.fail()288 }289 res.send(`${err.message} - ${err.code}`)290 },291 constraints: { secret: constraint }292 })293 294 fastify.route({295 method: 'GET',296 url: '/',297 constraints: { secret: 'alpha' },298 handler: (req, reply) => {299 reply.send({ hello: 'from alpha' })300 }301 })302 303 fastify.inject(304 {305 method: 'GET',306 url: '/'307 },308 (err, res) => {309 t.assert.ifError(err)310 t.assert.strictEqual(res.body, 'Unexpected error from async constraint - FST_ERR_ASYNC_CONSTRAINT')311 done()312 }313 )314})315 316test('Should supply Fastify request to the logger in frameworkErrors wrapper - FST_ERR_ASYNC_CONSTRAINT', (t, done) => {317 t.plan(8)318 319 const constraint = {320 name: 'secret',321 storage: function () {322 const secrets = {}323 return {324 get: (secret) => { return secrets[secret] || null },325 set: (secret, store) => { secrets[secret] = store }326 }327 },328 deriveConstraint: (req, ctx, done) => {329 done(Error('kaboom'))330 },331 validate () { return true }332 }333 334 const REQ_ID = 'REQ-1234'335 const logStream = split(JSON.parse)336 337 const fastify = Fastify({338 constraints: { secret: constraint },339 frameworkErrors: function (err, req, res) {340 t.assert.deepStrictEqual(req.id, REQ_ID)341 t.assert.deepStrictEqual(req.raw.httpVersion, '1.1')342 res.send(`${err.message} - ${err.code}`)343 },344 logger: {345 stream: logStream,346 serializers: {347 req (request) {348 t.assert.deepStrictEqual(request.id, REQ_ID)349 return { httpVersion: request.raw.httpVersion }350 }351 }352 },353 genReqId: () => REQ_ID354 })355 356 fastify.route({357 method: 'GET',358 url: '/',359 constraints: { secret: 'alpha' },360 handler: (req, reply) => {361 reply.send({ hello: 'from alpha' })362 }363 })364 365 logStream.on('data', (json) => {366 t.assert.deepStrictEqual(json.msg, 'incoming request')367 t.assert.deepStrictEqual(json.reqId, REQ_ID)368 t.assert.deepStrictEqual(json.req.httpVersion, '1.1')369 })370 371 fastify.inject(372 {373 method: 'GET',374 url: '/'375 },376 (err, res) => {377 t.assert.ifError(err)378 t.assert.strictEqual(res.body, 'Unexpected error from async constraint - FST_ERR_ASYNC_CONSTRAINT')379 done()380 }381 )382})383 384test('Should honor disableRequestLogging option in frameworkErrors wrapper - FST_ERR_ASYNC_CONSTRAINT', (t, done) => {385 t.plan(2)386 387 const constraint = {388 name: 'secret',389 storage: function () {390 const secrets = {}391 return {392 get: (secret) => { return secrets[secret] || null },393 set: (secret, store) => { secrets[secret] = store }394 }395 },396 deriveConstraint: (req, ctx, done) => {397 done(Error('kaboom'))398 },399 validate () { return true }400 }401 402 const logStream = split(JSON.parse)403 404 const fastify = Fastify({405 constraints: { secret: constraint },406 disableRequestLogging: true,407 frameworkErrors: function (err, req, res) {408 res.send(`${err.message} - ${err.code}`)409 },410 logger: {411 stream: logStream,412 serializers: {413 req () {414 t.assert.fail('should not be called')415 },416 res () {417 t.assert.fail('should not be called')418 }419 }420 }421 })422 423 fastify.route({424 method: 'GET',425 url: '/',426 constraints: { secret: 'alpha' },427 handler: (req, reply) => {428 reply.send({ hello: 'from alpha' })429 }430 })431 432 logStream.on('data', (json) => {433 t.assert.fail('should not be called')434 })435 436 fastify.inject(437 {438 method: 'GET',439 url: '/'440 },441 (err, res) => {442 t.assert.ifError(err)443 t.assert.strictEqual(res.body, 'Unexpected error from async constraint - FST_ERR_ASYNC_CONSTRAINT')444 done()445 }446 )447})448 