New:Socket for Asana Is Now Available.Learn more
Get Started

fastify

Package Overview
Dependencies
Maintainers
6
Versions
325
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastify - npm Package Compare versions

Comparing version
5.11.3
to
5.12.0
+131
test/reply-media-type.test.js
'use strict'
const { test } = require('node:test')
const Fastify = require('..')
test('reply.mediaType should match the content-type header', async (t) => {
t.plan(2)
const fastify = Fastify()
fastify.get('/', (request, reply) => {
reply.type('application/json')
t.assert.strictEqual(reply.mediaType, 'application/json')
reply.send({ mediaType: reply.mediaType })
})
const response = await fastify.inject({
method: 'GET',
url: '/'
})
const body = await response.json()
t.assert.strictEqual(body.mediaType, 'application/json')
})
test('reply.mediaType should strip the charset parameter', async (t) => {
t.plan(2)
const fastify = Fastify()
fastify.get('/', (request, reply) => {
reply.header('content-type', 'application/json; charset=utf-8')
t.assert.strictEqual(reply.mediaType, 'application/json')
reply.send({ mediaType: reply.mediaType })
})
const response = await fastify.inject({
method: 'GET',
url: '/'
})
const body = await response.json()
t.assert.strictEqual(body.mediaType, 'application/json')
})
test('reply.mediaType should strip the space', async (t) => {
t.plan(2)
const fastify = Fastify()
fastify.get('/', (request, reply) => {
reply.header('content-type', ' application/json ; charset=utf-8')
t.assert.strictEqual(reply.mediaType, 'application/json')
reply.send({ mediaType: reply.mediaType })
})
const response = await fastify.inject({
method: 'GET',
url: '/'
})
const body = await response.json()
t.assert.strictEqual(body.mediaType, 'application/json')
})
test('reply.mediaType is undefined when content-type is not set', async (t) => {
t.plan(2)
const fastify = Fastify()
fastify.get('/', (request, reply) => {
t.assert.strictEqual(reply.mediaType, undefined)
reply.send({ mediaType: reply.mediaType })
})
const response = await fastify.inject({
method: 'GET',
url: '/'
})
const body = await response.json()
t.assert.strictEqual(body.mediaType, undefined)
})
test('reply.mediaType supported in hooks', async (t) => {
t.plan(5)
const fastify = Fastify()
fastify.get('/', {
preHandler: (request, reply, done) => {
reply.type('application/json')
t.assert.strictEqual(reply.mediaType, 'application/json')
done()
},
preSerialization: (request, reply, payload, done) => {
t.assert.strictEqual(reply.mediaType, 'application/json')
done(null, payload)
},
onSend: (request, reply, payload, done) => {
t.assert.strictEqual(reply.mediaType, 'application/json')
done(null, payload)
}
}, (request, reply) => {
t.assert.strictEqual(reply.mediaType, 'application/json')
reply.send({ mediaType: reply.mediaType })
})
const response = await fastify.inject({
method: 'GET',
url: '/'
})
const body = await response.json()
t.assert.strictEqual(body.mediaType, 'application/json')
})
test('reply.mediaType should reflect the last type set', async (t) => {
t.plan(2)
const fastify = Fastify()
fastify.get('/', (request, reply) => {
reply.type('application/json')
reply.type('text/plain')
t.assert.strictEqual(reply.mediaType, 'text/plain')
reply.send(`mediaType = ${reply.mediaType}`)
})
const response = await fastify.inject({
method: 'GET',
url: '/'
})
const body = response.body
t.assert.strictEqual(body, 'mediaType = text/plain')
})
+34
-2

@@ -259,5 +259,37 @@ <h1 align="center">Serverless</h1>

#### Per-route logging
Google Cloud Functions exposes one entry point for your Fastify instance, so
the dashboard may show all HTTP traffic under that function. Instead of
deploying one function per endpoint, keep the single Fastify instance and emit
a structured log line after each request with the matched route:
```js
fastify.addHook('onResponse', async (request, reply) => {
request.log.info({
route: request.routeOptions.url,
method: request.method,
statusCode: reply.statusCode,
responseTime: reply.elapsedTime
}, 'request completed')
})
```
`request.routeOptions.url` is the route pattern, so `/users/123` and
`/users/456` are grouped under `/users/:id`. With Fastify's logger enabled, the
fields are emitted as structured log fields, as described in the [Cloud
Logging structured logging documentation](https://cloud.google.com/logging/docs/structured-logging)
and the [Cloud Functions logging guide](https://cloud.google.com/functions/docs/monitoring/logging).
In Cloud Logging, create a [log-based
metric](https://cloud.google.com/logging/docs/logs-based-metrics) or filter on
`jsonPayload.route` to get per-route request counts, latency, and error rates.
The same hook works when deploying through Firebase Functions with `onRequest`.
### References
- [Google Cloud Functions - Node.js Quickstart
](https://docs.cloud.google.com/run/docs/quickstarts/functions/deploy-functions-gcloud)
](https://cloud.google.com/run/docs/quickstarts/functions/deploy-functions-gcloud)
- [Cloud Logging - Structured Logging](https://cloud.google.com/logging/docs/structured-logging)
- [Cloud Logging - Log-based Metrics](https://cloud.google.com/logging/docs/logs-based-metrics)
- [Cloud Functions - Logging](https://cloud.google.com/functions/docs/monitoring/logging)

@@ -598,2 +630,2 @@ ## Google Firebase Functions

[here](
https://vercel.com/docs/fluid-compute#enabling-fluid-compute).
https://vercel.com/docs/fluid-compute#enabling-fluid-compute).

@@ -9,2 +9,3 @@ <h1 align="center">Fastify</h1>

- [.statusCode](#statuscode)
- [.mediaType](#mediatype)
- [.server](#server)

@@ -55,2 +56,3 @@ - [.header(key, value)](#headerkey-value)

since the request was received by Fastify.
- `.mediaType` - The media type extracted from `Content-Type` header.
- `.server` - A reference to the fastify instance object.

@@ -134,3 +136,15 @@ - `.header(name, value)` - Sets a response header.

```
### .mediaType
<a id="mediatype"></a>
Returns the media type extracted from `Content-Type` header. When `Content-Type`
header is missing, it will return `undefined`.
```js
if (reply.mediaType === 'image/gif') {
const versionBuffer = new Uint8Array(reply.payload, 3, 3)
reply.header('x-gif-version', new TextDecoder().decode(versionBuffer))
}
```
### .server

@@ -137,0 +151,0 @@ <a id="server"></a>

+1
-1
'use strict'
const VERSION = '5.11.3'
const VERSION = '5.12.0'

@@ -5,0 +5,0 @@ const Avvio = require('avvio')

@@ -186,3 +186,6 @@ 'use strict'

get mediaType () { return `${this.#type}/${this.#subtype}` }
get mediaType () {
if (this.#valid === false) return undefined
return `${this.#type}/${this.#subtype}`
}

@@ -189,0 +192,0 @@ get type () { return this.#type }

@@ -96,2 +96,8 @@ 'use strict'

},
mediaType: {
get () {
const contentTypeHeader = this[kReplyHeaders]['content-type']
return ContentType.from(contentTypeHeader).mediaType
}
},
server: {

@@ -258,5 +264,9 @@ get () {

Reply.prototype.removeHeader = function (key) {
key = key.toLowerCase()
// Node.js does not like headers with keys set to undefined,
// so we have to delete the key.
delete this[kReplyHeaders][key.toLowerCase()]
delete this[kReplyHeaders][key]
if (!this.raw.headersSent) {
this.raw.removeHeader(key)
}
return this

@@ -263,0 +273,0 @@ }

{
"name": "fastify",
"version": "5.11.3",
"version": "5.12.0",
"description": "Fast and low overhead web framework, for Node.js",

@@ -170,3 +170,2 @@ "main": "fastify.js",

"@jsumners/line-reporter": "^1.0.1",
"@sinonjs/fake-timers": "^11.2.2",
"@stylistic/eslint-plugin": "^5.1.0",

@@ -218,3 +217,3 @@ "@stylistic/eslint-plugin-js": "^4.1.0",

"pino": "^9.14.0 || ^10.1.0",
"process-warning": "^5.0.0",
"process-warning": "^5.1.0",
"rfdc": "^1.3.1",

@@ -221,0 +220,0 @@ "secure-json-parse": "^4.0.0",

@@ -22,2 +22,3 @@ # Sponsors

- [N-iX](https://www.n-ix.com/)
- [TestMu AI](https://www.testmuai.com/?utm_medium=sponsor&utm_source=fastify)

@@ -24,0 +25,0 @@ ## Tier 2

'use strict'
const { test } = require('node:test')
const { spyWarning } = require('process-warning')
const Fastify = require('..')
const keys = require('../lib/symbols')
const { FST_ERR_CTP_ALREADY_PRESENT, FST_ERR_CTP_INVALID_TYPE, FST_ERR_CTP_INVALID_MEDIA_TYPE } = require('../lib/errors')
const { FSTSEC001 } = require('../lib/warnings')

@@ -491,14 +493,9 @@ const first = function (req, payload, done) {}

test('Warning against improper content-type - regexp', async t => {
await t.test('improper regex - text plain', (t, done) => {
await t.test('improper regex - text plain', async (t) => {
t.plan(2)
const spyData = spyWarning(FSTSEC001)
t.after(spyData.restore)
const fastify = Fastify()
process.on('warning', onWarning)
function onWarning (warning) {
t.assert.strictEqual(warning.name, 'FastifySecurity')
t.assert.strictEqual(warning.code, 'FSTSEC001')
done()
}
t.after(() => process.removeListener('warning', onWarning))
fastify.removeAllContentTypeParsers()

@@ -508,16 +505,14 @@ fastify.addContentTypeParser(/text\/plain/, function (request, body, done) {

})
await fastify.ready()
t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['text\\/plain'], result: true }])
t.assert.strictEqual(spyData.callCount(), 1)
})
await t.test('improper regex - application json', (t, done) => {
await t.test('improper regex - application json', async (t) => {
t.plan(2)
const spyData = spyWarning(FSTSEC001)
t.after(spyData.restore)
const fastify = Fastify()
process.on('warning', onWarning)
function onWarning (warning) {
t.assert.strictEqual(warning.name, 'FastifySecurity')
t.assert.strictEqual(warning.code, 'FSTSEC001')
done()
}
t.after(() => process.removeListener('warning', onWarning))
fastify.removeAllContentTypeParsers()

@@ -528,2 +523,5 @@

})
t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['application\\/json'], result: true }])
t.assert.deepEqual(spyData.callCount(), 1)
})

@@ -530,0 +528,0 @@ })

@@ -49,8 +49,11 @@ 'use strict'

t.assert.equal(found.isEmpty, true)
t.assert.equal(found.mediaType, undefined)
found = new ContentType('undefined')
t.assert.equal(found.isEmpty, true)
t.assert.equal(found.mediaType, undefined)
found = new ContentType()
t.assert.equal(found.isEmpty, true)
t.assert.equal(found.mediaType, undefined)
})

@@ -62,2 +65,3 @@

t.assert.equal(found.isValid, false)
t.assert.equal(found.mediaType, undefined)

@@ -64,0 +68,0 @@ found = new ContentType('foo /bar')

@@ -7,3 +7,2 @@ 'use strict'

const symbols = require('../lib/symbols')
const { waitForCb } = require('./toolkit')
const assert = require('node:assert')

@@ -13,2 +12,34 @@

function waitForCb (options) {
let count = null
let done = false
let iResolve
let iReject
function stepIn () {
if (done) {
iReject(new Error('Unexpected done call'))
return
}
if (--count) {
return
}
done = true
iResolve()
}
const patience = new Promise((resolve, reject) => {
iResolve = resolve
iReject = reject
})
count = options.steps || 1
done = false
return { stepIn, patience }
}
module.exports.waitForCb = waitForCb
/**

@@ -499,1 +530,42 @@ * @param method HTTP request method

}
module.exports.partialDeepStrictEqual = function partialDeepStrictEqual (actual, expected) {
if (typeof expected !== 'object' || expected === null) {
return actual === expected
}
if (typeof actual !== 'object' || actual === null) {
return false
}
if (Array.isArray(expected)) {
if (!Array.isArray(actual)) return false
if (expected.length > actual.length) return false
for (let i = 0; i < expected.length; i++) {
if (!partialDeepStrictEqual(actual[i], expected[i])) {
return false
}
}
return true
}
for (const key of Object.keys(expected)) {
if (!(key in actual)) return false
if (!partialDeepStrictEqual(actual[key], expected[key])) {
return false
}
}
return true
}
module.exports.assertNoWarning = function (t) {
function doNotWarn () {
t.assert.fail('no warning')
}
process.on('warning', doNotWarn)
t.after(() => {
process.off('warning', doNotWarn)
})
}

@@ -7,4 +7,3 @@ 'use strict'

const fs = require('node:fs')
const { sleep } = require('./helper')
const { waitForCb } = require('./toolkit')
const { sleep, waitForCb } = require('./helper')

@@ -11,0 +10,0 @@ process.removeAllListeners('warning')

@@ -37,3 +37,3 @@ 'use strict'

test('Once called, Reply should return an object with methods', t => {
t.plan(15)
t.plan(16)
const response = { res: 'res' }

@@ -53,2 +53,3 @@ const context = {

t.assert.strictEqual(typeof reply.code, 'function')
t.assert.strictEqual(typeof reply.mediaType, 'string')
t.assert.strictEqual(typeof reply.status, 'function')

@@ -1119,2 +1120,76 @@ t.assert.strictEqual(typeof reply.header, 'function')

test('reply.removeHeader removes raw headers', async t => {
t.plan(9)
const fastify = require('../../')()
t.after(() => fastify.close())
fastify.get('/headers', function (req, reply) {
reply.raw.setHeader('X-Foo', 'raw')
t.assert.strictEqual(reply.getHeader('x-foo'), 'raw')
t.assert.strictEqual(reply.getHeaders()['x-foo'], 'raw')
t.assert.strictEqual(reply.hasHeader('x-foo'), true)
t.assert.strictEqual(reply.removeHeader('x-FoO'), reply)
t.assert.strictEqual(reply.getHeader('x-foo'), undefined)
t.assert.strictEqual(Object.hasOwn(reply.getHeaders(), 'x-foo'), false)
t.assert.strictEqual(reply.hasHeader('x-foo'), false)
t.assert.strictEqual(reply.removeHeader('X-FOO'), reply)
reply.send()
})
const fastifyServer = await fastify.listen({ port: 0 })
const response = await fetch(`${fastifyServer}/headers`)
t.assert.strictEqual(response.headers.get('x-foo'), null)
})
test('reply.removeHeader removes layered headers', async t => {
t.plan(7)
const fastify = require('../../')()
t.after(() => fastify.close())
fastify.get('/headers', function (req, reply) {
reply.raw.setHeader('x-foo', 'raw')
reply.header('x-foo', 'fastify')
t.assert.strictEqual(reply.getHeader('x-foo'), 'fastify')
t.assert.strictEqual(reply.getHeaders()['x-foo'], 'fastify')
t.assert.strictEqual(reply.removeHeader('x-foo'), reply)
t.assert.strictEqual(reply.getHeader('x-foo'), undefined)
t.assert.strictEqual(Object.hasOwn(reply.getHeaders(), 'x-foo'), false)
t.assert.strictEqual(reply.hasHeader('x-foo'), false)
reply.send()
})
const fastifyServer = await fastify.listen({ port: 0 })
const response = await fetch(`${fastifyServer}/headers`)
t.assert.strictEqual(response.headers.get('x-foo'), null)
})
test('reply.removeHeader does not throw after headers are sent', async t => {
t.plan(3)
const fastify = require('../../')()
t.after(() => fastify.close())
fastify.get('/headers', function (req, reply) {
reply.hijack()
reply.raw.setHeader('x-foo', 'raw')
reply.raw.flushHeaders()
t.assert.strictEqual(reply.raw.headersSent, true)
t.assert.doesNotThrow(() => reply.removeHeader('x-foo'))
reply.raw.end()
})
const fastifyServer = await fastify.listen({ port: 0 })
const response = await fetch(`${fastifyServer}/headers`)
t.assert.strictEqual(response.headers.get('x-foo'), 'raw')
})
test('reply.header can reset the value', async t => {

@@ -1121,0 +1196,0 @@ t.plan(1)

@@ -7,2 +7,3 @@ 'use strict'

const helper = require('./helper')
const { assertNoWarning } = require('./helper')

@@ -17,12 +18,6 @@ let localhost

test('listen works without arguments', async t => {
const doNotWarn = () => {
t.assert.fail('should not be deprecated')
}
process.on('warning', doNotWarn)
assertNoWarning(t)
const fastify = Fastify()
t.after(() => {
fastify.close()
process.removeListener('warning', doNotWarn)
})
await fastify.listen()

@@ -32,15 +27,10 @@ const address = fastify.server.address()

t.assert.ok(address.port > 0)
await fastify.close()
})
test('Async/await listen with arguments', async t => {
const doNotWarn = () => {
t.assert.fail('should not be deprecated')
}
process.on('warning', doNotWarn)
assertNoWarning(t)
const fastify = Fastify()
t.after(() => {
fastify.close()
process.removeListener('warning', doNotWarn)
})
const addr = await fastify.listen({ port: 0, host: '0.0.0.0' })

@@ -61,2 +51,3 @@ const address = fastify.server.address()

})
await fastify.close()
})

@@ -66,16 +57,10 @@

t.plan(2)
const doNotWarn = () => {
t.assert.fail('should not be deprecated')
}
process.on('warning', doNotWarn)
assertNoWarning(t)
const fastify = Fastify()
t.after(() => {
fastify.close()
process.removeListener('warning', doNotWarn)
})
fastify.listen({ port: 0 }, (err) => {
t.assert.ifError(err)
t.assert.strictEqual(fastify.server.address().address, localhost)
done()
fastify.close(done)
})

@@ -86,12 +71,5 @@ })

t.plan(1)
const doNotWarn = () => {
t.assert.fail('should not be deprecated')
}
process.on('warning', doNotWarn)
assertNoWarning(t)
const fastify = Fastify()
t.after(() => {
fastify.close()
process.removeListener('warning', doNotWarn)
})
fastify.listen({

@@ -107,3 +85,3 @@ port: 0,

t.assert.ifError(err)
done()
fastify.close(done)
})

@@ -128,13 +106,5 @@ })

test('listen works with undefined host', async t => {
const doNotWarn = () => {
t.assert.fail('should not be deprecated')
}
process.on('warning', doNotWarn)
assertNoWarning(t)
const fastify = Fastify()
t.after(() => fastify.close())
t.after(() => {
fastify.close()
process.removeListener('warning', doNotWarn)
})
await fastify.listen({ host: undefined, port: 0 })

@@ -144,16 +114,10 @@ const address = fastify.server.address()

t.assert.ok(address.port > 0)
await fastify.close()
})
test('listen works with null host', async t => {
const doNotWarn = () => {
t.fail('should not be deprecated')
}
process.on('warning', doNotWarn)
assertNoWarning(t)
const fastify = Fastify()
t.after(() => fastify.close())
t.after(() => {
fastify.close()
process.removeListener('warning', doNotWarn)
})
await fastify.listen({ host: null, port: 0 })

@@ -163,2 +127,3 @@ const address = fastify.server.address()

t.assert.ok(address.port > 0)
await fastify.close()
})

@@ -5,4 +5,5 @@ 'use strict'

const net = require('node:net')
const { once } = require('node:events')
const { spyWarning } = require('process-warning')
const Fastify = require('../fastify')
const { once } = require('node:events')
const { FSTWRN003 } = require('../lib/warnings.js')

@@ -106,8 +107,3 @@

process.on('warning', onWarning)
function onWarning (warning) {
t.assert.strictEqual(warning.name, 'FastifyWarning')
t.assert.strictEqual(warning.code, FSTWRN003.code)
}
const spyData = spyWarning(FSTWRN003)
const fastify = Fastify()

@@ -117,9 +113,10 @@

await fastify.close()
process.removeListener('warning', onWarning)
FSTWRN003.emitted = false
spyData.restore()
})
fastify.listen({ port: 0 }, async function doNotUseAsyncCallback () {
t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['listen method'], result: true }])
t.assert.strictEqual(spyData.callCount(), 1)
done()
})
})

@@ -17,3 +17,3 @@ 'use strict'

const { createTempFile, request } = require('./logger-test-utils')
const { partialDeepStrictEqual } = require('../toolkit')
const { partialDeepStrictEqual } = require('../helper')

@@ -20,0 +20,0 @@ t.test('logger instantiation', { timeout: 60000 }, async (t) => {

@@ -14,3 +14,3 @@ 'use strict'

const { request } = require('./logger-test-utils')
const { partialDeepStrictEqual } = require('../toolkit')
const { partialDeepStrictEqual } = require('../helper')

@@ -17,0 +17,0 @@ t.test('logging', { timeout: 60000 }, async (t) => {

@@ -12,3 +12,3 @@ 'use strict'

const { request } = require('./logger-test-utils')
const { partialDeepStrictEqual } = require('../toolkit')
const { partialDeepStrictEqual } = require('../helper')

@@ -15,0 +15,0 @@ t.test('request', { timeout: 60000 }, async (t) => {

@@ -10,3 +10,3 @@ 'use strict'

const Fastify = require('../../fastify')
const { partialDeepStrictEqual } = require('../toolkit')
const { partialDeepStrictEqual } = require('../helper')
const { on } = stream

@@ -13,0 +13,0 @@

@@ -6,3 +6,2 @@ 'use strict'

const fp = require('fastify-plugin')
const fakeTimer = require('@sinonjs/fake-timers')
const { FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER } = require('../lib/errors')

@@ -50,3 +49,5 @@

t.plan(5)
const clock = fakeTimer.install({ shouldClearNativeTimers: true })
t.mock.timers.enable({
apis: ['setTimeout', 'Date']
})

@@ -56,3 +57,3 @@ const fastify = Fastify()

// default time elapsed without calling done
clock.tick(10000)
t.mock.timers.tick(10000)
})

@@ -70,3 +71,3 @@

t.after(clock.uninstall)
t.after(() => t.mock.timers.reset())
})

@@ -73,0 +74,0 @@

@@ -5,3 +5,3 @@ 'use strict'

const Fastify = require('..')
const { waitForCb } = require('./toolkit')
const { waitForCb } = require('./helper')

@@ -8,0 +8,0 @@ test('Prefix options should add a prefix for all the routes inside a register / 1', (t, testDone) => {

@@ -7,2 +7,3 @@ 'use strict'

const Fastify = require('..')
const { assertNoWarning } = require('./helper')

@@ -285,2 +286,4 @@ test('Creates a HEAD route for a GET one with prefixTrailingSlash', async (t) => {

test('no warning for exposeHeadRoute', async t => {
assertNoWarning(t)
const fastify = Fastify()

@@ -297,13 +300,3 @@

const listener = (w) => {
t.assert.fail('no warning')
}
process.on('warning', listener)
await fastify.listen({ port: 0 })
process.removeListener('warning', listener)
await fastify.close()
await fastify.ready()
})
'use strict'
const { test } = require('node:test')
const fp = require('fastify-plugin')
const { spyWarning } = require('process-warning')
const Fastify = require('..')
const fp = require('fastify-plugin')
const deepClone = require('rfdc')({ circles: true, proto: false })

@@ -10,3 +11,3 @@ const Ajv = require('ajv')

const { FSTWRN001 } = require('../lib/warnings')
const { waitForCb } = require('./toolkit')
const { waitForCb } = require('./helper')

@@ -324,15 +325,7 @@ const echoParams = (req, reply) => { reply.send(req.params) }

t.plan(4)
const spyData = spyWarning(FSTWRN001)
t.after(spyData.restore)
const fastify = Fastify()
process.on('warning', onWarning)
function onWarning (warning) {
t.assert.strictEqual(warning.name, 'FastifyWarning')
t.assert.strictEqual(warning.code, FSTWRN001.code)
}
t.after(() => {
process.removeListener('warning', onWarning)
FSTWRN001.emitted = false
})
fastify.post('/:id', {

@@ -351,2 +344,4 @@ handler: echoParams,

t.assert.strictEqual(res.statusCode, 200)
t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['headers', 'POST', '/:id'], result: true }])
t.assert.strictEqual(spyData.callCount(), 1)
testDone()

@@ -358,15 +353,7 @@ })

t.plan(4)
const spyData = spyWarning(FSTWRN001)
t.after(spyData.restore)
const fastify = Fastify()
process.on('warning', onWarning)
function onWarning (warning) {
t.assert.strictEqual(warning.name, 'FastifyWarning')
t.assert.strictEqual(warning.code, FSTWRN001.code)
}
t.after(() => {
process.removeListener('warning', onWarning)
FSTWRN001.emitted = false
})
fastify.post('/:id', {

@@ -385,2 +372,4 @@ handler: echoParams,

t.assert.strictEqual(res.statusCode, 200)
t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['body', 'POST', '/:id'], result: true }])
t.assert.strictEqual(spyData.callCount(), 1)
testDone()

@@ -392,15 +381,7 @@ })

t.plan(4)
const spyData = spyWarning(FSTWRN001)
t.after(spyData.restore)
const fastify = Fastify()
process.on('warning', onWarning)
function onWarning (warning) {
t.assert.strictEqual(warning.name, 'FastifyWarning')
t.assert.strictEqual(warning.code, FSTWRN001.code)
}
t.after(() => {
process.removeListener('warning', onWarning)
FSTWRN001.emitted = false
})
fastify.post('/:id', {

@@ -419,2 +400,4 @@ handler: echoParams,

t.assert.strictEqual(res.statusCode, 200)
t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['querystring', 'POST', '/:id'], result: true }])
t.assert.strictEqual(spyData.callCount(), 1)
testDone()

@@ -426,15 +409,7 @@ })

t.plan(4)
const spyData = spyWarning(FSTWRN001)
t.after(spyData.restore)
const fastify = Fastify()
process.on('warning', onWarning)
function onWarning (warning) {
t.assert.strictEqual(warning.name, 'FastifyWarning')
t.assert.strictEqual(warning.code, FSTWRN001.code)
}
t.after(() => {
process.removeListener('warning', onWarning)
FSTWRN001.emitted = false
})
fastify.post('/:id', {

@@ -453,2 +428,4 @@ handler: echoParams,

t.assert.strictEqual(res.statusCode, 200)
t.assert.deepStrictEqual(spyData.calls, [{ arguments: ['params', 'POST', '/:id'], result: true }])
t.assert.strictEqual(spyData.callCount(), 1)
testDone()

@@ -459,23 +436,8 @@ })

test('Should emit a warning for every route with undefined schema', (t, testDone) => {
t.plan(16)
t.plan(9)
const spyData = spyWarning(FSTWRN001)
t.after(spyData.restore)
const fastify = Fastify()
let runs = 0
const expectedWarningEmitted = [0, 1, 2, 3]
// It emits 4 warnings:
// - 2 - GET and HEAD for /undefinedParams/:id
// - 2 - GET and HEAD for /undefinedBody/:id
// => 3 x 4 assertions = 12 assertions
function onWarning (warning) {
t.assert.strictEqual(warning.name, 'FastifyWarning')
t.assert.strictEqual(warning.code, FSTWRN001.code)
t.assert.strictEqual(runs++, expectedWarningEmitted.shift())
}
process.on('warning', onWarning)
t.after(() => {
process.removeListener('warning', onWarning)
FSTWRN001.emitted = false
})
fastify.get('/undefinedParams/:id', {

@@ -509,2 +471,11 @@ handler: echoParams,

t.assert.strictEqual(res.statusCode, 200)
// fastify.inject run in series
// last callback recieve all warnings at once
// GET /undefinedParams/123
t.assert.deepStrictEqual(spyData.calls[0], { arguments: ['params', 'GET', '/undefinedParams/:id'], result: true })
t.assert.deepStrictEqual(spyData.calls[1], { arguments: ['params', 'HEAD', '/undefinedParams/:id'], result: true })
// GET /undefinedBody/123
t.assert.deepStrictEqual(spyData.calls[2], { arguments: ['body', 'GET', '/undefinedBody/:id'], result: true })
t.assert.deepStrictEqual(spyData.calls[3], { arguments: ['body', 'HEAD', '/undefinedBody/:id'], result: true })
t.assert.strictEqual(spyData.callCount(), 4)
testDone()

@@ -511,0 +482,0 @@ })

@@ -6,3 +6,3 @@ 'use strict'

const ContentType = require('../lib/content-type')
const { waitForCb } = require('./toolkit')
const { waitForCb } = require('./helper')

@@ -9,0 +9,0 @@ const echoBody = (req, reply) => { reply.send(req.body) }

@@ -12,3 +12,3 @@ 'use strict'

const proxyquire = require('proxyquire')
const { waitForCb } = require('./toolkit')
const { waitForCb } = require('./helper')

@@ -15,0 +15,0 @@ test('Ajv plugins array parameter', (t, testDone) => {

@@ -8,3 +8,3 @@ 'use strict'

const Schema = require('fluent-json-schema')
const { waitForCb } = require('./toolkit')
const { waitForCb } = require('./helper')
const { kRequestContentType } = require('../lib/symbols')

@@ -11,0 +11,0 @@

@@ -10,3 +10,3 @@ 'use strict'

const Fastify = require('..')
const { waitForCb } = require('./toolkit')
const { waitForCb } = require('./helper')

@@ -13,0 +13,0 @@ test('onSend hook stream', t => {

'use strict'
exports.waitForCb = function (options) {
let count = null
let done = false
let iResolve
let iReject
function stepIn () {
if (done) {
iReject(new Error('Unexpected done call'))
return
}
if (--count) {
return
}
done = true
iResolve()
}
const patience = new Promise((resolve, reject) => {
iResolve = resolve
iReject = reject
})
count = options.steps || 1
done = false
return { stepIn, patience }
}
exports.partialDeepStrictEqual = function partialDeepStrictEqual (actual, expected) {
if (typeof expected !== 'object' || expected === null) {
return actual === expected
}
if (typeof actual !== 'object' || actual === null) {
return false
}
if (Array.isArray(expected)) {
if (!Array.isArray(actual)) return false
if (expected.length > actual.length) return false
for (let i = 0; i < expected.length; i++) {
if (!partialDeepStrictEqual(actual[i], expected[i])) {
return false
}
}
return true
}
for (const key of Object.keys(expected)) {
if (!(key in actual)) return false
if (!partialDeepStrictEqual(actual[key], expected[key])) {
return false
}
}
return true
}

Sorry, the diff of this file is too big to display