fastify 3.25.2 → 3.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/build/build-validation.js +2 -0
- package/docs/Guides/Index.md +2 -0
- package/docs/Guides/Prototype-Poisoning.md +391 -0
- package/docs/Guides/Recommendations.md +1 -1
- package/docs/Reference/Plugins.md +4 -4
- package/docs/Reference/Request.md +3 -0
- package/docs/Reference/Server.md +16 -2
- package/docs/Reference/TypeScript.md +1 -1
- package/fastify.d.ts +2 -1
- package/fastify.js +23 -5
- package/lib/errors.js +5 -0
- package/lib/noop-set.js +10 -0
- package/lib/pluginUtils.js +5 -0
- package/lib/reply.js +16 -6
- package/lib/route.js +34 -1
- package/lib/symbols.js +3 -1
- package/lib/warnings.js +1 -1
- package/package.json +7 -7
- package/test/404s.test.js +1 -1
- package/test/bundler/esbuild/bundler-test.js +31 -0
- package/test/bundler/esbuild/package.json +10 -0
- package/test/bundler/esbuild/src/fail-plugin-version.js +12 -0
- package/test/bundler/esbuild/src/index.js +7 -0
- package/test/bundler/webpack/bundler-test.js +15 -4
- package/test/bundler/webpack/src/fail-plugin-version.js +1 -3
- package/test/bundler/webpack/src/index.js +1 -3
- package/test/close.test.js +38 -0
- package/test/custom-parser.test.js +30 -31
- package/test/noop-set.test.js +19 -0
- package/test/plugin.name.display.js +10 -0
- package/test/plugin.test.js +18 -0
- package/test/route.test.js +12 -0
- package/test/schema-serialization.test.js +41 -0
- package/test/types/fastify.test-d.ts +17 -0
- package/test/types/hooks.test-d.ts +28 -4
- package/test/types/instance.test-d.ts +25 -0
- package/test/versioned-routes.test.js +27 -3
- package/types/hooks.d.ts +19 -19
- package/types/instance.d.ts +13 -1
- package/types/schema.d.ts +14 -0
package/lib/noop-set.js
ADDED
package/lib/pluginUtils.js
CHANGED
|
@@ -14,6 +14,11 @@ function getMeta (fn) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function getPluginName (func) {
|
|
17
|
+
const display = getDisplayName(func)
|
|
18
|
+
if (display) {
|
|
19
|
+
return display
|
|
20
|
+
}
|
|
21
|
+
|
|
17
22
|
// let's see if this is a file, and in that case use that
|
|
18
23
|
// this is common for plugins
|
|
19
24
|
const cache = require.cache
|
package/lib/reply.js
CHANGED
|
@@ -365,12 +365,18 @@ function preserializeHookEnd (err, request, reply, payload) {
|
|
|
365
365
|
return
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
368
|
+
try {
|
|
369
|
+
if (reply[kReplySerializer] !== null) {
|
|
370
|
+
payload = reply[kReplySerializer](payload)
|
|
371
|
+
} else if (reply.context && reply.context[kReplySerializerDefault]) {
|
|
372
|
+
payload = reply.context[kReplySerializerDefault](payload, reply.raw.statusCode)
|
|
373
|
+
} else {
|
|
374
|
+
payload = serialize(reply.context, payload, reply.raw.statusCode)
|
|
375
|
+
}
|
|
376
|
+
} catch (e) {
|
|
377
|
+
wrapSeralizationError(e, reply)
|
|
378
|
+
onErrorHook(reply, e)
|
|
379
|
+
return
|
|
374
380
|
}
|
|
375
381
|
|
|
376
382
|
flatstr(payload)
|
|
@@ -378,6 +384,10 @@ function preserializeHookEnd (err, request, reply, payload) {
|
|
|
378
384
|
onSendHook(reply, payload)
|
|
379
385
|
}
|
|
380
386
|
|
|
387
|
+
function wrapSeralizationError (error, reply) {
|
|
388
|
+
error.serialization = reply.context.config
|
|
389
|
+
}
|
|
390
|
+
|
|
381
391
|
function onSendHook (reply, payload) {
|
|
382
392
|
if (reply.context.onSend !== null) {
|
|
383
393
|
reply[kReplySent] = true
|
package/lib/route.js
CHANGED
|
@@ -8,6 +8,7 @@ const supportedMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT', 'OPTI
|
|
|
8
8
|
const { normalizeSchema } = require('./schemas')
|
|
9
9
|
const { parseHeadOnSendHandlers } = require('./headRoute')
|
|
10
10
|
const warning = require('./warnings')
|
|
11
|
+
const { kRequestAcceptVersion } = require('./symbols')
|
|
11
12
|
|
|
12
13
|
const {
|
|
13
14
|
compileSchemasForValidation,
|
|
@@ -17,7 +18,8 @@ const {
|
|
|
17
18
|
const {
|
|
18
19
|
FST_ERR_SCH_VALIDATION_BUILD,
|
|
19
20
|
FST_ERR_SCH_SERIALIZATION_BUILD,
|
|
20
|
-
FST_ERR_DEFAULT_ROUTE_INVALID_TYPE
|
|
21
|
+
FST_ERR_DEFAULT_ROUTE_INVALID_TYPE,
|
|
22
|
+
FST_ERR_INVALID_URL
|
|
21
23
|
} = require('./errors')
|
|
22
24
|
|
|
23
25
|
const {
|
|
@@ -40,6 +42,7 @@ const {
|
|
|
40
42
|
} = require('./symbols.js')
|
|
41
43
|
|
|
42
44
|
function buildRouting (options) {
|
|
45
|
+
const { keepAliveConnections } = options
|
|
43
46
|
const router = FindMyWay(options.config)
|
|
44
47
|
|
|
45
48
|
let avvio
|
|
@@ -97,6 +100,10 @@ function buildRouting (options) {
|
|
|
97
100
|
|
|
98
101
|
// Convert shorthand to extended route declaration
|
|
99
102
|
function prepareRoute (method, url, options, handler) {
|
|
103
|
+
if (typeof url !== 'string') {
|
|
104
|
+
throw new FST_ERR_INVALID_URL(typeof url)
|
|
105
|
+
}
|
|
106
|
+
|
|
100
107
|
if (!handler && typeof options === 'function') {
|
|
101
108
|
handler = options // for support over direct function calls such as fastify.get() options are reused as the handler
|
|
102
109
|
options = {}
|
|
@@ -344,6 +351,23 @@ function buildRouting (options) {
|
|
|
344
351
|
}
|
|
345
352
|
}
|
|
346
353
|
|
|
354
|
+
// When server.forceCloseConnections is true, we will collect any requests
|
|
355
|
+
// that have indicated they want persistence so that they can be reaped
|
|
356
|
+
// on server close. Otherwise, the container is a noop container.
|
|
357
|
+
const connHeader = String.prototype.toLowerCase.call(req.headers.connection || '')
|
|
358
|
+
if (connHeader === 'keep-alive') {
|
|
359
|
+
if (keepAliveConnections.has(req.socket) === false) {
|
|
360
|
+
keepAliveConnections.add(req.socket)
|
|
361
|
+
req.socket.on('close', removeTrackedSocket.bind({ keepAliveConnections, socket: req.socket }))
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// we revert the changes in defaultRoute
|
|
366
|
+
if (req.headers[kRequestAcceptVersion] !== undefined) {
|
|
367
|
+
req.headers['accept-version'] = req.headers[kRequestAcceptVersion]
|
|
368
|
+
req.headers[kRequestAcceptVersion] = undefined
|
|
369
|
+
}
|
|
370
|
+
|
|
347
371
|
const id = req.headers[requestIdHeader] || genReqId(req)
|
|
348
372
|
|
|
349
373
|
const loggerBinding = {
|
|
@@ -478,6 +502,15 @@ function preParsingHookRunner (functions, request, reply, cb) {
|
|
|
478
502
|
next(null, request[kRequestPayloadStream])
|
|
479
503
|
}
|
|
480
504
|
|
|
505
|
+
/**
|
|
506
|
+
* Used within the route handler as a `net.Socket.close` event handler.
|
|
507
|
+
* The purpose is to remove a socket from the tracked sockets collection when
|
|
508
|
+
* the socket has naturally timed out.
|
|
509
|
+
*/
|
|
510
|
+
function removeTrackedSocket () {
|
|
511
|
+
this.keepAliveConnections.delete(this.socket)
|
|
512
|
+
}
|
|
513
|
+
|
|
481
514
|
function noop () { }
|
|
482
515
|
|
|
483
516
|
module.exports = { buildRouting, validateBodyLimitOption }
|
package/lib/symbols.js
CHANGED
|
@@ -21,6 +21,7 @@ const keys = {
|
|
|
21
21
|
kReply: Symbol('fastify.Reply'),
|
|
22
22
|
kRequest: Symbol('fastify.Request'),
|
|
23
23
|
kRequestPayloadStream: Symbol('fastify.RequestPayloadStream'),
|
|
24
|
+
kRequestAcceptVersion: Symbol('fastify.RequestAcceptVersion'),
|
|
24
25
|
kCanSetNotFoundHandler: Symbol('fastify.canSetNotFoundHandler'),
|
|
25
26
|
kFourOhFour: Symbol('fastify.404'),
|
|
26
27
|
kFourOhFourLevelInstance: Symbol('fastify.404LogLevelInstance'),
|
|
@@ -43,7 +44,8 @@ const keys = {
|
|
|
43
44
|
kPluginNameChain: Symbol('fastify.pluginNameChain'),
|
|
44
45
|
// This symbol is only meant to be used for fastify tests and should not be used for any other purpose
|
|
45
46
|
kTestInternals: Symbol('fastify.testInternals'),
|
|
46
|
-
kErrorHandler: Symbol('fastify.errorHandler')
|
|
47
|
+
kErrorHandler: Symbol('fastify.errorHandler'),
|
|
48
|
+
kKeepAliveConnections: Symbol('fastify.keepAliveConnections')
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
module.exports = keys
|
package/lib/warnings.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.27.1",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"lint:typescript": "eslint -c types/.eslintrc.json types/**/*.d.ts test/types/**/*.test-d.ts",
|
|
17
17
|
"prepublishOnly": "tap --no-check-coverage test/internals/version.test.js",
|
|
18
18
|
"test": "npm run lint && npm run unit && npm run test:typescript",
|
|
19
|
-
"test:ci": "npm run
|
|
19
|
+
"test:ci": "npm run unit -- -R terse --cov --coverage-report=lcovonly && npm run test:typescript",
|
|
20
20
|
"test:report": "npm run lint && npm run unit:report && npm run test:typescript",
|
|
21
21
|
"test:typescript": "tsd",
|
|
22
22
|
"unit": "tap -J test/*.test.js test/*/*.test.js",
|
|
@@ -129,6 +129,7 @@
|
|
|
129
129
|
"@types/pino": "^6.0.1",
|
|
130
130
|
"@typescript-eslint/eslint-plugin": "^4.5.0",
|
|
131
131
|
"@typescript-eslint/parser": "^4.5.0",
|
|
132
|
+
"JSONStream": "^1.3.5",
|
|
132
133
|
"ajv": "^6.0.0",
|
|
133
134
|
"ajv-errors": "^1.0.1",
|
|
134
135
|
"ajv-formats": "^2.1.1",
|
|
@@ -152,12 +153,11 @@
|
|
|
152
153
|
"form-data": "^4.0.0",
|
|
153
154
|
"frameguard": "^4.0.0",
|
|
154
155
|
"h2url": "^0.2.0",
|
|
155
|
-
"helmet": "^
|
|
156
|
+
"helmet": "^5.0.1",
|
|
156
157
|
"hide-powered-by": "^1.1.0",
|
|
157
158
|
"hsts": "^2.2.0",
|
|
158
|
-
"http-errors": "^
|
|
159
|
+
"http-errors": "^2.0.0",
|
|
159
160
|
"ienoopen": "^1.1.0",
|
|
160
|
-
"JSONStream": "^1.3.5",
|
|
161
161
|
"license-checker": "^25.0.1",
|
|
162
162
|
"pem": "^1.14.4",
|
|
163
163
|
"proxyquire": "^2.1.3",
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
"then-sleep": "^1.0.1",
|
|
174
174
|
"tsd": "^0.19.0",
|
|
175
175
|
"typescript": "^4.0.2",
|
|
176
|
-
"undici": "^3.3.
|
|
176
|
+
"undici": "^3.3.6",
|
|
177
177
|
"x-xss-protection": "^2.0.0",
|
|
178
178
|
"yup": "^0.32.0"
|
|
179
179
|
},
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
"avvio": "^7.1.2",
|
|
184
184
|
"fast-json-stringify": "^2.5.2",
|
|
185
185
|
"fastify-error": "^0.3.0",
|
|
186
|
-
"
|
|
186
|
+
"process-warning": "^1.0.0",
|
|
187
187
|
"find-my-way": "^4.5.0",
|
|
188
188
|
"flatstr": "^1.0.12",
|
|
189
189
|
"light-my-request": "^4.2.0",
|
package/test/404s.test.js
CHANGED
|
@@ -1221,7 +1221,7 @@ test('preHandler option for setNotFoundHandler', t => {
|
|
|
1221
1221
|
})
|
|
1222
1222
|
|
|
1223
1223
|
// https://github.com/fastify/fastify/issues/2229
|
|
1224
|
-
t.test('preHandler hook in setNotFoundHandler should be called when callNotFound', t => {
|
|
1224
|
+
t.test('preHandler hook in setNotFoundHandler should be called when callNotFound', { timeout: 40000 }, t => {
|
|
1225
1225
|
t.plan(2)
|
|
1226
1226
|
const fastify = Fastify()
|
|
1227
1227
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const fastifySuccess = require('./dist/success')
|
|
6
|
+
const fastifyFailPlugin = require('./dist/failPlugin')
|
|
7
|
+
|
|
8
|
+
test('Bundled package should work', (t) => {
|
|
9
|
+
t.plan(4)
|
|
10
|
+
fastifySuccess.ready((err) => {
|
|
11
|
+
t.error(err)
|
|
12
|
+
fastifySuccess.inject(
|
|
13
|
+
{
|
|
14
|
+
method: 'GET',
|
|
15
|
+
url: '/'
|
|
16
|
+
},
|
|
17
|
+
(error, res) => {
|
|
18
|
+
t.error(error)
|
|
19
|
+
t.equal(res.statusCode, 200)
|
|
20
|
+
t.same(res.json(), { hello: 'world' })
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
})
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('Bundled package should not work with bad plugin version', (t) => {
|
|
27
|
+
t.plan(1)
|
|
28
|
+
fastifyFailPlugin.ready((err) => {
|
|
29
|
+
t.match(err.message, /expected '9.x' fastify version/i)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.0.1",
|
|
3
|
+
"scripts": {
|
|
4
|
+
"bundle": "esbuild success=src/index.js failPlugin=src/fail-plugin-version.js --bundle --outdir=dist --platform=node",
|
|
5
|
+
"test": "npm run bundle && node bundler-test.js"
|
|
6
|
+
},
|
|
7
|
+
"devDependencies": {
|
|
8
|
+
"esbuild": "^0.14.11"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const fp = require('fastify-plugin')
|
|
2
|
+
const fastify = require('../../../../')()
|
|
3
|
+
|
|
4
|
+
fastify.get('/', function (request, reply) {
|
|
5
|
+
reply.send({ hello: 'world' })
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
fastify.register(fp((instance, opts, done) => {
|
|
9
|
+
done()
|
|
10
|
+
}, { fastify: '9.x' }))
|
|
11
|
+
|
|
12
|
+
module.exports = fastify
|
|
@@ -5,16 +5,27 @@ const test = t.test
|
|
|
5
5
|
const fastifySuccess = require('./dist/success')
|
|
6
6
|
const fastifyFailPlugin = require('./dist/failPlugin')
|
|
7
7
|
|
|
8
|
-
test('Bundled package should work', t => {
|
|
9
|
-
t.plan(
|
|
8
|
+
test('Bundled package should work', (t) => {
|
|
9
|
+
t.plan(4)
|
|
10
10
|
fastifySuccess.ready((err) => {
|
|
11
11
|
t.error(err)
|
|
12
|
+
fastifySuccess.inject(
|
|
13
|
+
{
|
|
14
|
+
method: 'GET',
|
|
15
|
+
url: '/'
|
|
16
|
+
},
|
|
17
|
+
(error, res) => {
|
|
18
|
+
t.error(error)
|
|
19
|
+
t.equal(res.statusCode, 200)
|
|
20
|
+
t.same(res.json(), { hello: 'world' })
|
|
21
|
+
}
|
|
22
|
+
)
|
|
12
23
|
})
|
|
13
24
|
})
|
|
14
25
|
|
|
15
|
-
test('Bundled package should not work with bad plugin version', t => {
|
|
26
|
+
test('Bundled package should not work with bad plugin version', (t) => {
|
|
16
27
|
t.plan(1)
|
|
17
28
|
fastifyFailPlugin.ready((err) => {
|
|
18
|
-
t.
|
|
29
|
+
t.match(err.message, /expected '9.x' fastify version/i)
|
|
19
30
|
})
|
|
20
31
|
})
|
package/test/close.test.js
CHANGED
|
@@ -291,3 +291,41 @@ test('Cannot be reopened the closed server has listen callback', async t => {
|
|
|
291
291
|
t.ok(err)
|
|
292
292
|
})
|
|
293
293
|
})
|
|
294
|
+
|
|
295
|
+
test('shutsdown while keep-alive connections are active (non-async)', t => {
|
|
296
|
+
t.plan(5)
|
|
297
|
+
|
|
298
|
+
const timeoutTime = 2 * 60 * 1000
|
|
299
|
+
const fastify = Fastify({ forceCloseConnections: true })
|
|
300
|
+
|
|
301
|
+
fastify.server.setTimeout(timeoutTime)
|
|
302
|
+
fastify.server.keepAliveTimeout = timeoutTime
|
|
303
|
+
|
|
304
|
+
fastify.get('/', (req, reply) => {
|
|
305
|
+
reply.send({ hello: 'world' })
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
fastify.listen(0, (err, address) => {
|
|
309
|
+
t.error(err)
|
|
310
|
+
|
|
311
|
+
const client = new Client(
|
|
312
|
+
'http://localhost:' + fastify.server.address().port,
|
|
313
|
+
{ keepAliveTimeout: 1 * 60 * 1000 }
|
|
314
|
+
)
|
|
315
|
+
client.request({ path: '/', method: 'GET' }, (err, response) => {
|
|
316
|
+
t.error(err)
|
|
317
|
+
t.equal(client.closed, false)
|
|
318
|
+
|
|
319
|
+
fastify.close((err) => {
|
|
320
|
+
t.error(err)
|
|
321
|
+
|
|
322
|
+
// Due to the nature of the way we reap these keep-alive connections,
|
|
323
|
+
// there hasn't been enough time before the server fully closed in order
|
|
324
|
+
// for the client to have seen the socket get destroyed. The mere fact
|
|
325
|
+
// that we have reached this callback is enough indication that the
|
|
326
|
+
// feature being tested works as designed.
|
|
327
|
+
t.equal(client.closed, false)
|
|
328
|
+
})
|
|
329
|
+
})
|
|
330
|
+
})
|
|
331
|
+
})
|
|
@@ -1314,9 +1314,10 @@ test('contentTypeParser should add a custom parser with RegExp value', t => {
|
|
|
1314
1314
|
})
|
|
1315
1315
|
})
|
|
1316
1316
|
|
|
1317
|
-
test('contentTypeParser should add multiple custom parsers with RegExp values', t => {
|
|
1318
|
-
t.plan(
|
|
1317
|
+
test('contentTypeParser should add multiple custom parsers with RegExp values', async t => {
|
|
1318
|
+
t.plan(6)
|
|
1319
1319
|
const fastify = Fastify()
|
|
1320
|
+
t.teardown(fastify.close.bind(fastify))
|
|
1320
1321
|
|
|
1321
1322
|
fastify.post('/', (req, reply) => {
|
|
1322
1323
|
reply.send(req.body)
|
|
@@ -1340,48 +1341,46 @@ test('contentTypeParser should add multiple custom parsers with RegExp values',
|
|
|
1340
1341
|
})
|
|
1341
1342
|
})
|
|
1342
1343
|
|
|
1343
|
-
fastify.
|
|
1344
|
-
t.error(err)
|
|
1344
|
+
await fastify.ready()
|
|
1345
1345
|
|
|
1346
|
-
|
|
1346
|
+
{
|
|
1347
|
+
const response = await fastify.inject({
|
|
1347
1348
|
method: 'POST',
|
|
1348
|
-
|
|
1349
|
-
|
|
1349
|
+
path: '/',
|
|
1350
|
+
payload: '{"hello":"world"}',
|
|
1350
1351
|
headers: {
|
|
1351
1352
|
'Content-Type': 'application/vnd.hello+json'
|
|
1352
1353
|
}
|
|
1353
|
-
}, (err, response, body) => {
|
|
1354
|
-
t.error(err)
|
|
1355
|
-
t.equal(response.statusCode, 200)
|
|
1356
|
-
t.same(body.toString(), JSON.stringify({ hello: 'world' }))
|
|
1357
1354
|
})
|
|
1355
|
+
t.equal(response.statusCode, 200)
|
|
1356
|
+
t.same(response.payload.toString(), '{"hello":"world"}')
|
|
1357
|
+
}
|
|
1358
1358
|
|
|
1359
|
-
|
|
1359
|
+
{
|
|
1360
|
+
const response = await fastify.inject({
|
|
1360
1361
|
method: 'POST',
|
|
1361
|
-
|
|
1362
|
-
|
|
1362
|
+
path: '/',
|
|
1363
|
+
payload: '{"hello":"world"}',
|
|
1363
1364
|
headers: {
|
|
1364
1365
|
'Content-Type': 'application/test+xml'
|
|
1365
1366
|
}
|
|
1366
|
-
}, (err, response, body) => {
|
|
1367
|
-
t.error(err)
|
|
1368
|
-
t.equal(response.statusCode, 200)
|
|
1369
|
-
t.same(body.toString(), 'xml')
|
|
1370
1367
|
})
|
|
1368
|
+
t.equal(response.statusCode, 200)
|
|
1369
|
+
t.same(response.payload.toString(), 'xml')
|
|
1370
|
+
}
|
|
1371
1371
|
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
})
|
|
1372
|
+
await fastify.inject({
|
|
1373
|
+
method: 'POST',
|
|
1374
|
+
path: '/',
|
|
1375
|
+
payload: 'abcdefg',
|
|
1376
|
+
headers: {
|
|
1377
|
+
'Content-Type': 'application/+myExtension'
|
|
1378
|
+
}
|
|
1379
|
+
}).then((response) => {
|
|
1380
|
+
t.equal(response.statusCode, 200)
|
|
1381
|
+
t.same(response.payload.toString(), 'abcdefgmyExtension')
|
|
1382
|
+
}).catch((err) => {
|
|
1383
|
+
t.error(err)
|
|
1385
1384
|
})
|
|
1386
1385
|
})
|
|
1387
1386
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const tap = require('tap')
|
|
4
|
+
const noopSet = require('../lib/noop-set')
|
|
5
|
+
|
|
6
|
+
tap.test('does a lot of nothing', async t => {
|
|
7
|
+
const aSet = noopSet()
|
|
8
|
+
t.type(aSet, 'object')
|
|
9
|
+
|
|
10
|
+
const item = {}
|
|
11
|
+
aSet.add(item)
|
|
12
|
+
aSet.add({ another: 'item' })
|
|
13
|
+
aSet.delete(item)
|
|
14
|
+
t.equal(aSet.has(item), true)
|
|
15
|
+
|
|
16
|
+
for (const i of aSet) {
|
|
17
|
+
t.fail('should not have any items', i)
|
|
18
|
+
}
|
|
19
|
+
})
|
package/test/plugin.test.js
CHANGED
|
@@ -41,6 +41,24 @@ test('plugin metadata - ignore prefix', t => {
|
|
|
41
41
|
}
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
+
test('plugin metadata - naming plugins', async t => {
|
|
45
|
+
t.plan(2)
|
|
46
|
+
const fastify = Fastify()
|
|
47
|
+
|
|
48
|
+
fastify.register(require('./plugin.name.display'))
|
|
49
|
+
fastify.register(function (fastify, opts, done) {
|
|
50
|
+
// one line
|
|
51
|
+
t.equal(fastify.pluginName, 'function (fastify, opts, done) { -- // one line')
|
|
52
|
+
done()
|
|
53
|
+
})
|
|
54
|
+
fastify.register(function fooBar (fastify, opts, done) {
|
|
55
|
+
t.equal(fastify.pluginName, 'fooBar')
|
|
56
|
+
done()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
await fastify.ready()
|
|
60
|
+
})
|
|
61
|
+
|
|
44
62
|
test('fastify.register with fastify-plugin should not encapsulate his code', t => {
|
|
45
63
|
t.plan(10)
|
|
46
64
|
const fastify = Fastify()
|
package/test/route.test.js
CHANGED
|
@@ -8,6 +8,7 @@ const sget = require('simple-get').concat
|
|
|
8
8
|
const joi = require('@hapi/joi')
|
|
9
9
|
const Fastify = require('..')
|
|
10
10
|
const proxyquire = require('proxyquire')
|
|
11
|
+
const { FST_ERR_INVALID_URL } = require('../lib/errors')
|
|
11
12
|
|
|
12
13
|
test('route', t => {
|
|
13
14
|
t.plan(9)
|
|
@@ -1268,3 +1269,14 @@ test('Correct error message is produced if "path" option is used', t => {
|
|
|
1268
1269
|
})
|
|
1269
1270
|
}, new Error('Error Handler for POST:/test route, if defined, must be a function'))
|
|
1270
1271
|
})
|
|
1272
|
+
|
|
1273
|
+
test('invalid url attribute - non string URL', t => {
|
|
1274
|
+
t.plan(1)
|
|
1275
|
+
const fastify = Fastify()
|
|
1276
|
+
|
|
1277
|
+
try {
|
|
1278
|
+
fastify.get(/^\/(donations|skills|blogs)/, () => {})
|
|
1279
|
+
} catch (error) {
|
|
1280
|
+
t.equal(error.code, FST_ERR_INVALID_URL().code)
|
|
1281
|
+
}
|
|
1282
|
+
})
|
|
@@ -670,3 +670,44 @@ test('error in custom schema serialize compiler, throw FST_ERR_SCH_SERIALIZATION
|
|
|
670
670
|
t.equal(err.code, 'FST_ERR_SCH_SERIALIZATION_BUILD')
|
|
671
671
|
})
|
|
672
672
|
})
|
|
673
|
+
|
|
674
|
+
test('Errors in searilizer sended to errorHandler', async t => {
|
|
675
|
+
let savedError
|
|
676
|
+
|
|
677
|
+
const fastify = Fastify()
|
|
678
|
+
fastify.get('/', {
|
|
679
|
+
schema: {
|
|
680
|
+
response: {
|
|
681
|
+
200: {
|
|
682
|
+
type: 'object',
|
|
683
|
+
properties: {
|
|
684
|
+
name: { type: 'string' },
|
|
685
|
+
power: { type: 'string' }
|
|
686
|
+
},
|
|
687
|
+
required: ['name']
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
}, function (req, reply) {
|
|
693
|
+
reply.code(200).send({ no: 'thing' })
|
|
694
|
+
})
|
|
695
|
+
fastify.setErrorHandler((error, request, reply) => {
|
|
696
|
+
savedError = error
|
|
697
|
+
reply.code(500).send(error)
|
|
698
|
+
})
|
|
699
|
+
|
|
700
|
+
const res = await fastify.inject('/')
|
|
701
|
+
|
|
702
|
+
t.equal(res.statusCode, 500)
|
|
703
|
+
|
|
704
|
+
// t.same(savedError, new Error('"name" is required!'));
|
|
705
|
+
t.same(res.json(), {
|
|
706
|
+
statusCode: 500,
|
|
707
|
+
error: 'Internal Server Error',
|
|
708
|
+
message: '"name" is required!'
|
|
709
|
+
})
|
|
710
|
+
t.ok(savedError, 'error presents')
|
|
711
|
+
t.ok(savedError.serialization, 'Serialization sign presents')
|
|
712
|
+
t.end()
|
|
713
|
+
})
|
|
@@ -57,6 +57,7 @@ fastify({ http2: true, https: {} }).inject({}, lightMyRequestCallback)
|
|
|
57
57
|
expectAssignable<FastifyInstance<http2.Http2Server, http2.Http2ServerRequest, http2.Http2ServerResponse>>(fastify({ http2: true }))
|
|
58
58
|
expectAssignable<FastifyInstance>(fastify({ ignoreTrailingSlash: true }))
|
|
59
59
|
expectAssignable<FastifyInstance>(fastify({ connectionTimeout: 1000 }))
|
|
60
|
+
expectAssignable<FastifyInstance>(fastify({ forceCloseConnections: true }))
|
|
60
61
|
expectAssignable<FastifyInstance>(fastify({ keepAliveTimeout: 1000 }))
|
|
61
62
|
expectAssignable<FastifyInstance>(fastify({ pluginTimeout: 1000 }))
|
|
62
63
|
expectAssignable<FastifyInstance>(fastify({ bodyLimit: 100 }))
|
|
@@ -178,6 +179,22 @@ expectAssignable<FastifyInstance>(fastify({
|
|
|
178
179
|
plugins: [() => { }]
|
|
179
180
|
}
|
|
180
181
|
}))
|
|
182
|
+
expectAssignable<FastifyInstance>(fastify({
|
|
183
|
+
ajv: {
|
|
184
|
+
customOptions: {
|
|
185
|
+
nullable: false
|
|
186
|
+
},
|
|
187
|
+
plugins: [[() => { }, 'keyword']]
|
|
188
|
+
}
|
|
189
|
+
}))
|
|
190
|
+
expectAssignable<FastifyInstance>(fastify({
|
|
191
|
+
ajv: {
|
|
192
|
+
customOptions: {
|
|
193
|
+
nullable: false
|
|
194
|
+
},
|
|
195
|
+
plugins: [[() => { }, ['keyword1', 'keyword2']]]
|
|
196
|
+
}
|
|
197
|
+
}))
|
|
181
198
|
expectAssignable<FastifyInstance>(fastify({ frameworkErrors: () => { } }))
|
|
182
199
|
expectAssignable<FastifyInstance>(fastify({
|
|
183
200
|
rewriteUrl: (req) => req.url === '/hi' ? '/hello' : req.url!
|