fastify 2.7.1 → 2.11.0
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/README.md +15 -4
- package/build/build-validation.js +8 -0
- package/docs/Benchmarking.md +2 -2
- package/docs/ContentTypeParser.md +12 -10
- package/docs/Decorators.md +14 -14
- package/docs/Ecosystem.md +7 -1
- package/docs/Errors.md +13 -8
- package/docs/Fluent-Schema.md +9 -12
- package/docs/Getting-Started.md +29 -25
- package/docs/HTTP2.md +1 -1
- package/docs/Hooks.md +201 -186
- package/docs/LTS.md +6 -7
- package/docs/Logging.md +10 -10
- package/docs/Middleware.md +59 -0
- package/docs/Plugins-Guide.md +52 -52
- package/docs/Plugins.md +3 -0
- package/docs/Reply.md +47 -3
- package/docs/Routes.md +120 -8
- package/docs/Server.md +69 -3
- package/docs/Serverless.md +76 -4
- package/docs/TypeScript.md +33 -10
- package/docs/Validation-and-Serialization.md +137 -1
- package/examples/typescript-server.ts +1 -1
- package/fastify.d.ts +52 -13
- package/fastify.js +68 -7
- package/lib/configValidator.js +99 -52
- package/lib/contentTypeParser.js +4 -4
- package/lib/context.js +2 -1
- package/lib/errors.js +21 -18
- package/lib/fourOhFour.js +10 -10
- package/lib/handleRequest.js +1 -2
- package/lib/logger.js +2 -2
- package/lib/pluginUtils.js +32 -0
- package/lib/reply.js +41 -6
- package/lib/route.js +37 -9
- package/lib/schemas.js +23 -12
- package/lib/symbols.js +4 -1
- package/lib/validation.js +15 -9
- package/lib/wrapThenable.js +1 -1
- package/package.json +34 -26
- package/test/404s.test.js +41 -1
- package/test/async-await.js +66 -0
- package/test/custom-parser.test.js +1 -1
- package/test/custom-querystring-parser.test.js +1 -1
- package/test/decorator.test.js +48 -0
- package/test/emit-warning.test.js +3 -3
- package/test/fastify-instance.test.js +29 -0
- package/test/helper.js +7 -7
- package/test/hooks-async.js +4 -3
- package/test/hooks.test.js +27 -8
- package/test/input-validation.test.js +126 -0
- package/test/internals/errors.test.js +9 -1
- package/test/internals/initialConfig.test.js +4 -2
- package/test/internals/plugin.test.js +4 -4
- package/test/internals/reply.test.js +78 -6
- package/test/internals/schemas.test.js +30 -0
- package/test/internals/validation.test.js +18 -0
- package/test/listen.test.js +1 -1
- package/test/logger.test.js +314 -1
- package/test/plugin.test.js +171 -0
- package/test/promises.test.js +55 -0
- package/test/proto-poisoning.test.js +76 -0
- package/test/route-hooks.test.js +109 -91
- package/test/route-prefix.test.js +1 -1
- package/test/schemas.test.js +450 -0
- package/test/shared-schemas.test.js +2 -2
- package/test/stream.test.js +10 -6
- package/test/throw.test.js +48 -2
- package/test/types/index.ts +86 -1
- package/test/validation-error-handling.test.js +3 -3
- package/test/versioned-routes.test.js +1 -1
- package/docs/Middlewares.md +0 -59
|
@@ -240,6 +240,77 @@ This example will returns:
|
|
|
240
240
|
| /sub | one, two |
|
|
241
241
|
| /deep | one, two, three |
|
|
242
242
|
|
|
243
|
+
<a name="ajv-plugins"></a>
|
|
244
|
+
#### Ajv Plugins
|
|
245
|
+
|
|
246
|
+
You can provide a list of plugins you want to use with Ajv:
|
|
247
|
+
|
|
248
|
+
> Refer to [`ajv options`](https://github.com/fastify/fastify/blob/master/docs/Server.md#factory-ajv) to check plugins format
|
|
249
|
+
|
|
250
|
+
```js
|
|
251
|
+
const fastify = require('fastify')({
|
|
252
|
+
ajv: {
|
|
253
|
+
plugins: [
|
|
254
|
+
require('ajv-merge-patch')
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
fastify.route({
|
|
260
|
+
method: 'POST',
|
|
261
|
+
url: '/',
|
|
262
|
+
schema: {
|
|
263
|
+
body: {
|
|
264
|
+
$patch: {
|
|
265
|
+
source: {
|
|
266
|
+
type: 'object',
|
|
267
|
+
properties: {
|
|
268
|
+
q: {
|
|
269
|
+
type: 'string'
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
with: [
|
|
274
|
+
{
|
|
275
|
+
op: 'add',
|
|
276
|
+
path: '/properties/q',
|
|
277
|
+
value: { type: 'number' }
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
handler (req, reply) {
|
|
284
|
+
reply.send({ ok: 1 })
|
|
285
|
+
}
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
fastify.route({
|
|
289
|
+
method: 'POST',
|
|
290
|
+
url: '/',
|
|
291
|
+
schema: {
|
|
292
|
+
body: {
|
|
293
|
+
$merge: {
|
|
294
|
+
source: {
|
|
295
|
+
type: 'object',
|
|
296
|
+
properties: {
|
|
297
|
+
q: {
|
|
298
|
+
type: 'string'
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
with: {
|
|
303
|
+
required: ['q']
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
handler (req, reply) {
|
|
309
|
+
reply.send({ ok: 1 })
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
```
|
|
313
|
+
|
|
243
314
|
<a name="schema-compiler"></a>
|
|
244
315
|
#### Schema Compiler
|
|
245
316
|
|
|
@@ -257,7 +328,9 @@ Fastify's [baseline ajv configuration](https://github.com/epoberezkin/ajv#option
|
|
|
257
328
|
}
|
|
258
329
|
```
|
|
259
330
|
|
|
260
|
-
This baseline configuration
|
|
331
|
+
This baseline configuration can be modified by providing [`ajv.customOptions`](https://github.com/fastify/fastify/blob/master/docs/Server.md#factory-ajv) to your Fastify factory.
|
|
332
|
+
|
|
333
|
+
If you want to change or set additional config options, you will need to create your own instance and override the existing one like:
|
|
261
334
|
|
|
262
335
|
```js
|
|
263
336
|
const fastify = require('fastify')()
|
|
@@ -280,6 +353,7 @@ fastify.setSchemaCompiler(function (schema) {
|
|
|
280
353
|
// Alternatively, you can set the schema compiler using the setter property:
|
|
281
354
|
fastify.schemaCompiler = function (schema) { return ajv.compile(schema) })
|
|
282
355
|
```
|
|
356
|
+
_**Note:** If you use a custom instance of any validator (even Ajv), you have to add schemas to the validator instead of fastify, since fastify's default validator is no longer used, and fastify's `addSchema` method has no idea what validator you are using._
|
|
283
357
|
|
|
284
358
|
But maybe you want to change the validation library. Perhaps you like `Joi`. In this case, you can use it to validate the url parameters, body, and query string!
|
|
285
359
|
|
|
@@ -300,6 +374,68 @@ In that case the function returned by `schemaCompiler` returns an object like:
|
|
|
300
374
|
* `error`: filled with an instance of `Error` or a string that describes the validation error
|
|
301
375
|
* `value`: the coerced value that passed the validation
|
|
302
376
|
|
|
377
|
+
<a name="schema-resolver"></a>
|
|
378
|
+
#### Schema Resolver
|
|
379
|
+
|
|
380
|
+
The `schemaResolver` is a function that works together with the `schemaCompiler`: you can't use it
|
|
381
|
+
with the default schema compiler. This feature is useful when you use complex schemas with `$ref` keyword
|
|
382
|
+
in your routes and a custom validator.
|
|
383
|
+
|
|
384
|
+
This is needed because all the schemas you add to your custom compiler are unknown to Fastify but it
|
|
385
|
+
need to resolve the `$ref` paths.
|
|
386
|
+
|
|
387
|
+
```js
|
|
388
|
+
const fastify = require('fastify')()
|
|
389
|
+
const Ajv = require('ajv')
|
|
390
|
+
const ajv = new Ajv()
|
|
391
|
+
|
|
392
|
+
ajv.addSchema({
|
|
393
|
+
$id: 'urn:schema:foo',
|
|
394
|
+
definitions: {
|
|
395
|
+
foo: { type: 'string' }
|
|
396
|
+
},
|
|
397
|
+
type: 'object',
|
|
398
|
+
properties: {
|
|
399
|
+
foo: { $ref: '#/definitions/foo' }
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
ajv.addSchema({
|
|
403
|
+
$id: 'urn:schema:response',
|
|
404
|
+
type: 'object',
|
|
405
|
+
required: ['foo'],
|
|
406
|
+
properties: {
|
|
407
|
+
foo: { $ref: 'urn:schema:foo#/definitions/foo' }
|
|
408
|
+
}
|
|
409
|
+
})
|
|
410
|
+
ajv.addSchema({
|
|
411
|
+
$id: 'urn:schema:request',
|
|
412
|
+
type: 'object',
|
|
413
|
+
required: ['foo'],
|
|
414
|
+
properties: {
|
|
415
|
+
foo: { $ref: 'urn:schema:foo#/definitions/foo' }
|
|
416
|
+
}
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
fastify.setSchemaCompiler(schema => ajv.compile(schema))
|
|
420
|
+
fastify.setSchemaResolver((ref) => {
|
|
421
|
+
return ajv.getSchema(ref).schema
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
fastify.route({
|
|
425
|
+
method: 'POST',
|
|
426
|
+
url: '/',
|
|
427
|
+
schema: {
|
|
428
|
+
body: ajv.getSchema('urn:schema:request').schema,
|
|
429
|
+
response: {
|
|
430
|
+
'2xx': ajv.getSchema('urn:schema:response').schema
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
handler (req, reply) {
|
|
434
|
+
reply.send({ foo: 'bar' })
|
|
435
|
+
}
|
|
436
|
+
})
|
|
437
|
+
```
|
|
438
|
+
|
|
303
439
|
<a name="serialization"></a>
|
|
304
440
|
### Serialization
|
|
305
441
|
Usually you will send your data to the clients via JSON, and Fastify has a powerful tool to help you, [fast-json-stringify](https://www.npmjs.com/package/fast-json-stringify), which is used if you have provided an output schema in the route options. We encourage you to use an output schema, as it will increase your throughput by 100-400% depending on your payload and will prevent accidental disclosure of sensitive information.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Most type annotations in this file are not strictly necessary but are
|
|
4
4
|
* included for this example.
|
|
5
5
|
*
|
|
6
|
-
* To run this example
|
|
6
|
+
* To run this example execute the following commands to install typescript,
|
|
7
7
|
* transpile the code, and start the server:
|
|
8
8
|
*
|
|
9
9
|
* npm i -g typescript
|
package/fastify.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/// <reference types="node" />
|
|
6
6
|
|
|
7
|
+
import * as ajv from 'ajv'
|
|
7
8
|
import * as http from 'http'
|
|
8
9
|
import * as http2 from 'http2'
|
|
9
10
|
import * as https from 'https'
|
|
@@ -21,7 +22,10 @@ declare function fastify(opts?: fastify.ServerOptionsAsSecureHttp2): fastify.Fas
|
|
|
21
22
|
// eslint-disable-next-line no-redeclare
|
|
22
23
|
declare namespace fastify {
|
|
23
24
|
|
|
24
|
-
type Plugin
|
|
25
|
+
type Plugin<HttpServer, HttpRequest, HttpResponse, Options, PluginInstance extends Function = Function> =
|
|
26
|
+
PluginInstance extends () => Promise<void> ?
|
|
27
|
+
((instance: FastifyInstance< HttpServer, HttpRequest, HttpResponse >, options: Options) => Promise<void>) :
|
|
28
|
+
(instance: FastifyInstance<HttpServer, HttpRequest, HttpResponse>, options: Options, callback: (err?: FastifyError) => void) => void;
|
|
25
29
|
|
|
26
30
|
type Middleware < HttpServer, HttpRequest, HttpResponse > = (this: FastifyInstance<HttpServer, HttpRequest, HttpResponse>, req: HttpRequest, res: HttpResponse, callback: (err?: FastifyError) => void) => void
|
|
27
31
|
|
|
@@ -81,7 +85,7 @@ declare namespace fastify {
|
|
|
81
85
|
req: FastifyRequest<HttpRequest, Query, Params, Headers, Body>,
|
|
82
86
|
reply: FastifyReply<HttpResponse>,
|
|
83
87
|
done: (err?: Error) => void,
|
|
84
|
-
) => void
|
|
88
|
+
) => void | Promise<any>
|
|
85
89
|
|
|
86
90
|
type FastifyMiddlewareWithPayload<
|
|
87
91
|
HttpServer = http.Server,
|
|
@@ -97,7 +101,7 @@ declare namespace fastify {
|
|
|
97
101
|
reply: FastifyReply<HttpResponse>,
|
|
98
102
|
payload: any,
|
|
99
103
|
done: (err?: Error, value?: any) => void,
|
|
100
|
-
) => void
|
|
104
|
+
) => void | Promise<any>
|
|
101
105
|
|
|
102
106
|
type RequestHandler<
|
|
103
107
|
HttpRequest = http.IncomingMessage,
|
|
@@ -113,6 +117,7 @@ declare namespace fastify {
|
|
|
113
117
|
) => void | Promise<any>
|
|
114
118
|
|
|
115
119
|
type SchemaCompiler = (schema: Object) => Function
|
|
120
|
+
type SchemaResolver = (ref: string) => Object
|
|
116
121
|
|
|
117
122
|
type BodyParser<HttpRequest, RawBody extends string | Buffer> =
|
|
118
123
|
| ((req: HttpRequest, rawBody: RawBody, done: (err: Error | null, body?: any) => void) => void)
|
|
@@ -165,6 +170,7 @@ declare namespace fastify {
|
|
|
165
170
|
headers(headers: { [key: string]: any }): FastifyReply<HttpResponse>
|
|
166
171
|
getHeader(name: string): string | undefined
|
|
167
172
|
hasHeader(name: string): boolean
|
|
173
|
+
removeHeader(name: string): FastifyReply<HttpResponse>
|
|
168
174
|
callNotFound(): void
|
|
169
175
|
getResponseTime(): number
|
|
170
176
|
type(contentType: string): FastifyReply<HttpResponse>
|
|
@@ -176,8 +182,12 @@ declare namespace fastify {
|
|
|
176
182
|
sent: boolean
|
|
177
183
|
res: HttpResponse
|
|
178
184
|
context: FastifyContext
|
|
185
|
+
request: FastifyRequest
|
|
179
186
|
}
|
|
180
187
|
type TrustProxyFunction = (addr: string, index: number) => boolean
|
|
188
|
+
type ServerFactoryHandlerFunction = (request: http.IncomingMessage | http2.Http2ServerRequest, response: http.ServerResponse | http2.Http2ServerResponse) => void
|
|
189
|
+
type ServerFactoryFunction = (handler: ServerFactoryHandlerFunction, options: ServerOptions) => http.Server | http2.Http2Server
|
|
190
|
+
|
|
181
191
|
interface ServerOptions {
|
|
182
192
|
caseSensitive?: boolean,
|
|
183
193
|
ignoreTrailingSlash?: boolean,
|
|
@@ -185,6 +195,7 @@ declare namespace fastify {
|
|
|
185
195
|
pluginTimeout?: number,
|
|
186
196
|
disableRequestLogging?: boolean,
|
|
187
197
|
onProtoPoisoning?: 'error' | 'remove' | 'ignore',
|
|
198
|
+
onConstructorPoisoning?: 'error' | 'remove' | 'ignore',
|
|
188
199
|
logger?: any,
|
|
189
200
|
trustProxy?: string | number | boolean | Array<string> | TrustProxyFunction,
|
|
190
201
|
maxParamLength?: number,
|
|
@@ -199,7 +210,15 @@ declare namespace fastify {
|
|
|
199
210
|
deriveVersion<Context>(req: Object, ctx?: Context) : String,
|
|
200
211
|
},
|
|
201
212
|
modifyCoreObjects?: boolean,
|
|
202
|
-
return503OnClosing?: boolean
|
|
213
|
+
return503OnClosing?: boolean,
|
|
214
|
+
genReqId?: () => number | string,
|
|
215
|
+
requestIdHeader?: string,
|
|
216
|
+
requestIdLogLabel?: string,
|
|
217
|
+
serverFactory?: ServerFactoryFunction,
|
|
218
|
+
ajv?: {
|
|
219
|
+
customOptions?: ajv.Options,
|
|
220
|
+
plugins?: Array<Array<any>|String>
|
|
221
|
+
}
|
|
203
222
|
}
|
|
204
223
|
interface ServerOptionsAsSecure extends ServerOptions {
|
|
205
224
|
https: http2.SecureServerOptions
|
|
@@ -241,9 +260,15 @@ declare namespace fastify {
|
|
|
241
260
|
> {
|
|
242
261
|
schema?: RouteSchema
|
|
243
262
|
attachValidation?: boolean
|
|
263
|
+
onSend?:
|
|
264
|
+
| FastifyMiddlewareWithPayload<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>
|
|
265
|
+
| Array<FastifyMiddlewareWithPayload<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>>
|
|
244
266
|
onRequest?:
|
|
245
267
|
| FastifyMiddleware<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>
|
|
246
268
|
| Array<FastifyMiddleware<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>>
|
|
269
|
+
onResponse?:
|
|
270
|
+
| FastifyMiddleware<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>
|
|
271
|
+
| Array<FastifyMiddleware<HttpServer, HttpRequest, HttpResponse>>
|
|
247
272
|
preParsing?:
|
|
248
273
|
| FastifyMiddleware<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>
|
|
249
274
|
| Array<FastifyMiddleware<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>>
|
|
@@ -256,10 +281,13 @@ declare namespace fastify {
|
|
|
256
281
|
preSerialization?:
|
|
257
282
|
FastifyMiddlewareWithPayload<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>
|
|
258
283
|
| Array<FastifyMiddlewareWithPayload<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>>
|
|
284
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>
|
|
259
285
|
schemaCompiler?: SchemaCompiler
|
|
260
286
|
bodyLimit?: number
|
|
261
287
|
logLevel?: string
|
|
288
|
+
logSerializers?: Object
|
|
262
289
|
config?: any
|
|
290
|
+
version?: string
|
|
263
291
|
prefixTrailingSlash?: 'slash' | 'no-slash' | 'both'
|
|
264
292
|
}
|
|
265
293
|
|
|
@@ -286,6 +314,7 @@ declare namespace fastify {
|
|
|
286
314
|
interface RegisterOptions<HttpServer, HttpRequest, HttpResponse> {
|
|
287
315
|
[key: string]: any,
|
|
288
316
|
prefix?: string,
|
|
317
|
+
logSerializers?: Object
|
|
289
318
|
}
|
|
290
319
|
|
|
291
320
|
/**
|
|
@@ -362,7 +391,7 @@ declare namespace fastify {
|
|
|
362
391
|
get<Query = DefaultQuery, Params = DefaultParams, Headers = DefaultHeaders, Body = DefaultBody>(
|
|
363
392
|
url: string,
|
|
364
393
|
opts: RouteShorthandOptions<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
365
|
-
handler
|
|
394
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
366
395
|
): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
367
396
|
|
|
368
397
|
/**
|
|
@@ -379,7 +408,7 @@ declare namespace fastify {
|
|
|
379
408
|
put<Query = DefaultQuery, Params = DefaultParams, Headers = DefaultHeaders, Body = DefaultBody>(
|
|
380
409
|
url: string,
|
|
381
410
|
opts: RouteShorthandOptions<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
382
|
-
handler
|
|
411
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
383
412
|
): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
384
413
|
|
|
385
414
|
/**
|
|
@@ -396,7 +425,7 @@ declare namespace fastify {
|
|
|
396
425
|
patch<Query = DefaultQuery, Params = DefaultParams, Headers = DefaultHeaders, Body = DefaultBody>(
|
|
397
426
|
url: string,
|
|
398
427
|
opts: RouteShorthandOptions<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
399
|
-
handler
|
|
428
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
400
429
|
): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
401
430
|
|
|
402
431
|
/**
|
|
@@ -413,7 +442,7 @@ declare namespace fastify {
|
|
|
413
442
|
post<Query = DefaultQuery, Params = DefaultParams, Headers = DefaultHeaders, Body = DefaultBody>(
|
|
414
443
|
url: string,
|
|
415
444
|
opts: RouteShorthandOptions<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
416
|
-
handler
|
|
445
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
417
446
|
): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
418
447
|
|
|
419
448
|
/**
|
|
@@ -430,7 +459,7 @@ declare namespace fastify {
|
|
|
430
459
|
head<Query = DefaultQuery, Params = DefaultParams, Headers = DefaultHeaders, Body = DefaultBody>(
|
|
431
460
|
url: string,
|
|
432
461
|
opts: RouteShorthandOptions<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
433
|
-
handler
|
|
462
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
434
463
|
): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
435
464
|
|
|
436
465
|
/**
|
|
@@ -447,7 +476,7 @@ declare namespace fastify {
|
|
|
447
476
|
delete<Query = DefaultQuery, Params = DefaultParams, Headers = DefaultHeaders, Body = DefaultBody>(
|
|
448
477
|
url: string,
|
|
449
478
|
opts: RouteShorthandOptions<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
450
|
-
handler
|
|
479
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
451
480
|
): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
452
481
|
|
|
453
482
|
/**
|
|
@@ -464,7 +493,7 @@ declare namespace fastify {
|
|
|
464
493
|
options<Query = DefaultQuery, Params = DefaultParams, Headers = DefaultHeaders, Body = DefaultBody>(
|
|
465
494
|
url: string,
|
|
466
495
|
opts: RouteShorthandOptions<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
467
|
-
handler
|
|
496
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
468
497
|
): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
469
498
|
|
|
470
499
|
/**
|
|
@@ -481,7 +510,7 @@ declare namespace fastify {
|
|
|
481
510
|
all<Query = DefaultQuery, Params = DefaultParams, Headers = DefaultHeaders, Body = DefaultBody>(
|
|
482
511
|
url: string,
|
|
483
512
|
opts: RouteShorthandOptions<HttpServer, HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
484
|
-
handler
|
|
513
|
+
handler?: RequestHandler<HttpRequest, HttpResponse, Query, Params, Headers, Body>,
|
|
485
514
|
): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
486
515
|
|
|
487
516
|
/**
|
|
@@ -532,10 +561,15 @@ declare namespace fastify {
|
|
|
532
561
|
*/
|
|
533
562
|
use(path: string, middleware: Middleware<HttpServer, HttpRequest, HttpResponse>): void
|
|
534
563
|
|
|
564
|
+
/**
|
|
565
|
+
* Apply the given middleware to routes matching the given multiple path
|
|
566
|
+
*/
|
|
567
|
+
use(path: string[], middleware: Middleware<HttpServer, HttpRequest, HttpResponse>): void
|
|
568
|
+
|
|
535
569
|
/**
|
|
536
570
|
* Registers a plugin
|
|
537
571
|
*/
|
|
538
|
-
register<
|
|
572
|
+
register<Options extends RegisterOptions<HttpServer, HttpRequest, HttpResponse>, PluginInstance extends Function>(plugin: Plugin<HttpServer, HttpRequest, HttpResponse, Options, PluginInstance>, options?: Options): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
539
573
|
|
|
540
574
|
/**
|
|
541
575
|
* `Register a callback that will be executed just after a register.
|
|
@@ -671,6 +705,11 @@ declare namespace fastify {
|
|
|
671
705
|
*/
|
|
672
706
|
setSchemaCompiler(schemaCompiler: SchemaCompiler): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
673
707
|
|
|
708
|
+
/**
|
|
709
|
+
* Set the schema resolver to find the `$ref` schema object
|
|
710
|
+
*/
|
|
711
|
+
setSchemaResolver(schemaResolver: SchemaResolver): FastifyInstance<HttpServer, HttpRequest, HttpResponse>
|
|
712
|
+
|
|
674
713
|
/**
|
|
675
714
|
* Create a shared schema
|
|
676
715
|
*/
|
package/fastify.js
CHANGED
|
@@ -10,9 +10,11 @@ const {
|
|
|
10
10
|
kBodyLimit,
|
|
11
11
|
kRoutePrefix,
|
|
12
12
|
kLogLevel,
|
|
13
|
+
kLogSerializers,
|
|
13
14
|
kHooks,
|
|
14
15
|
kSchemas,
|
|
15
16
|
kSchemaCompiler,
|
|
17
|
+
kSchemaResolver,
|
|
16
18
|
kReplySerializerDefault,
|
|
17
19
|
kContentTypeParser,
|
|
18
20
|
kReply,
|
|
@@ -21,7 +23,8 @@ const {
|
|
|
21
23
|
kFourOhFour,
|
|
22
24
|
kState,
|
|
23
25
|
kOptions,
|
|
24
|
-
kGlobalHooks
|
|
26
|
+
kGlobalHooks,
|
|
27
|
+
kPluginNameChain
|
|
25
28
|
} = require('./lib/symbols.js')
|
|
26
29
|
|
|
27
30
|
const { createServer } = require('./lib/server')
|
|
@@ -55,7 +58,7 @@ function build (options) {
|
|
|
55
58
|
validateBodyLimitOption(options.bodyLimit)
|
|
56
59
|
|
|
57
60
|
if (options.logger && options.logger.genReqId) {
|
|
58
|
-
process.emitWarning(
|
|
61
|
+
process.emitWarning("Using 'genReqId' in logger options is deprecated. Use fastify options instead. See: https://www.fastify.io/docs/latest/Server/#gen-request-id")
|
|
59
62
|
options.genReqId = options.logger.genReqId
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -66,6 +69,21 @@ function build (options) {
|
|
|
66
69
|
const requestIdLogLabel = options.requestIdLogLabel || 'reqId'
|
|
67
70
|
const bodyLimit = options.bodyLimit || defaultInitOptions.bodyLimit
|
|
68
71
|
const disableRequestLogging = options.disableRequestLogging || false
|
|
72
|
+
const ajvOptions = Object.assign({
|
|
73
|
+
customOptions: {},
|
|
74
|
+
plugins: []
|
|
75
|
+
}, options.ajv)
|
|
76
|
+
|
|
77
|
+
// Ajv options
|
|
78
|
+
if (!ajvOptions.customOptions || Object.prototype.toString.call(ajvOptions.customOptions) !== '[object Object]') {
|
|
79
|
+
throw new Error(`ajv.customOptions option should be an object, instead got '${typeof ajvOptions.customOptions}'`)
|
|
80
|
+
}
|
|
81
|
+
if (!ajvOptions.plugins || !Array.isArray(ajvOptions.plugins)) {
|
|
82
|
+
throw new Error(`ajv.plugins option should be an array, instead got '${typeof ajvOptions.customOptions}'`)
|
|
83
|
+
}
|
|
84
|
+
ajvOptions.plugins = ajvOptions.plugins.map(plugin => {
|
|
85
|
+
return Array.isArray(plugin) ? plugin : [plugin]
|
|
86
|
+
})
|
|
69
87
|
|
|
70
88
|
// Instance Fastify components
|
|
71
89
|
const { logger, hasLogger } = createLogger(options)
|
|
@@ -79,11 +97,13 @@ function build (options) {
|
|
|
79
97
|
options.requestIdLogLabel = requestIdLogLabel
|
|
80
98
|
options.modifyCoreObjects = modifyCoreObjects
|
|
81
99
|
options.disableRequestLogging = disableRequestLogging
|
|
100
|
+
options.ajv = ajvOptions
|
|
82
101
|
|
|
83
102
|
// Default router
|
|
84
103
|
const router = buildRouting({
|
|
85
104
|
config: {
|
|
86
105
|
defaultRoute: defaultRoute,
|
|
106
|
+
onBadUrl: onBadUrl,
|
|
87
107
|
ignoreTrailingSlash: options.ignoreTrailingSlash || defaultInitOptions.ignoreTrailingSlash,
|
|
88
108
|
maxParamLength: options.maxParamLength || defaultInitOptions.maxParamLength,
|
|
89
109
|
caseSensitive: options.caseSensitive,
|
|
@@ -116,11 +136,17 @@ function build (options) {
|
|
|
116
136
|
[kBodyLimit]: bodyLimit,
|
|
117
137
|
[kRoutePrefix]: '',
|
|
118
138
|
[kLogLevel]: '',
|
|
139
|
+
[kLogSerializers]: null,
|
|
119
140
|
[kHooks]: new Hooks(),
|
|
120
141
|
[kSchemas]: schemas,
|
|
121
142
|
[kSchemaCompiler]: null,
|
|
143
|
+
[kSchemaResolver]: null,
|
|
122
144
|
[kReplySerializerDefault]: null,
|
|
123
|
-
[kContentTypeParser]: new ContentTypeParser(
|
|
145
|
+
[kContentTypeParser]: new ContentTypeParser(
|
|
146
|
+
bodyLimit,
|
|
147
|
+
(options.onProtoPoisoning || defaultInitOptions.onProtoPoisoning),
|
|
148
|
+
(options.onConstructorPoisoning || defaultInitOptions.onConstructorPoisoning)
|
|
149
|
+
),
|
|
124
150
|
[kReply]: Reply.buildReply(Reply),
|
|
125
151
|
[kRequest]: Request.buildRequest(Request),
|
|
126
152
|
[kMiddlewares]: [],
|
|
@@ -130,6 +156,7 @@ function build (options) {
|
|
|
130
156
|
onRegister: []
|
|
131
157
|
},
|
|
132
158
|
[pluginUtils.registeredPlugins]: [],
|
|
159
|
+
[kPluginNameChain]: [],
|
|
133
160
|
// routes shorthand methods
|
|
134
161
|
delete: function _delete (url, opts, handler) {
|
|
135
162
|
return router.prepareRoute.call(this, 'DELETE', url, opts, handler)
|
|
@@ -169,6 +196,7 @@ function build (options) {
|
|
|
169
196
|
addSchema: addSchema,
|
|
170
197
|
getSchemas: schemas.getSchemas.bind(schemas),
|
|
171
198
|
setSchemaCompiler: setSchemaCompiler,
|
|
199
|
+
setSchemaResolver: setSchemaResolver,
|
|
172
200
|
setReplySerializer: setReplySerializer,
|
|
173
201
|
// custom parsers
|
|
174
202
|
addContentTypeParser: ContentTypeParser.helpers.addContentTypeParser,
|
|
@@ -224,6 +252,15 @@ function build (options) {
|
|
|
224
252
|
}
|
|
225
253
|
})
|
|
226
254
|
|
|
255
|
+
Object.defineProperty(fastify, 'pluginName', {
|
|
256
|
+
get: function () {
|
|
257
|
+
if (this[kPluginNameChain].length > 1) {
|
|
258
|
+
return this[kPluginNameChain].join(' -> ')
|
|
259
|
+
}
|
|
260
|
+
return this[kPluginNameChain][0]
|
|
261
|
+
}
|
|
262
|
+
})
|
|
263
|
+
|
|
227
264
|
// Install and configure Avvio
|
|
228
265
|
// Avvio will update the following Fastify methods:
|
|
229
266
|
// - register
|
|
@@ -330,13 +367,13 @@ function build (options) {
|
|
|
330
367
|
throwIfAlreadyStarted('Cannot call "addHook" when fastify instance is already started!')
|
|
331
368
|
|
|
332
369
|
// TODO: v3 instead of log a warning, throw an error
|
|
333
|
-
if (name === 'onSend' || name === 'preSerialization') {
|
|
370
|
+
if (name === 'onSend' || name === 'preSerialization' || name === 'onError') {
|
|
334
371
|
if (fn.constructor.name === 'AsyncFunction' && fn.length === 4) {
|
|
335
|
-
fastify.log.warn(
|
|
372
|
+
fastify.log.warn("Async function has too many arguments. Async hooks should not use the 'next' argument.", new Error().stack)
|
|
336
373
|
}
|
|
337
374
|
} else {
|
|
338
375
|
if (fn.constructor.name === 'AsyncFunction' && fn.length === 3) {
|
|
339
|
-
fastify.log.warn(
|
|
376
|
+
fastify.log.warn("Async function has too many arguments. Async hooks should not use the 'next' argument.", new Error().stack)
|
|
340
377
|
}
|
|
341
378
|
}
|
|
342
379
|
|
|
@@ -390,6 +427,15 @@ function build (options) {
|
|
|
390
427
|
fourOhFour.router.lookup(req, res)
|
|
391
428
|
}
|
|
392
429
|
|
|
430
|
+
function onBadUrl (path, req, res) {
|
|
431
|
+
const body = `{"error":"Bad Request","message":"'${path}' is not a valid url component","statusCode":400}`
|
|
432
|
+
res.writeHead(400, {
|
|
433
|
+
'Content-Type': 'application/json',
|
|
434
|
+
'Content-Length': body.length
|
|
435
|
+
})
|
|
436
|
+
res.end(body)
|
|
437
|
+
}
|
|
438
|
+
|
|
393
439
|
function setNotFoundHandler (opts, handler) {
|
|
394
440
|
throwIfAlreadyStarted('Cannot call "setNotFoundHandler" when fastify instance is already started!')
|
|
395
441
|
|
|
@@ -404,6 +450,13 @@ function build (options) {
|
|
|
404
450
|
return this
|
|
405
451
|
}
|
|
406
452
|
|
|
453
|
+
function setSchemaResolver (schemaRefResolver) {
|
|
454
|
+
throwIfAlreadyStarted('Cannot call "setSchemaResolver" when fastify instance is already started!')
|
|
455
|
+
|
|
456
|
+
this[kSchemaResolver] = schemaRefResolver
|
|
457
|
+
return this
|
|
458
|
+
}
|
|
459
|
+
|
|
407
460
|
function setReplySerializer (replySerializer) {
|
|
408
461
|
throwIfAlreadyStarted('Cannot call "setReplySerializer" when fastify instance is already started!')
|
|
409
462
|
|
|
@@ -424,7 +477,10 @@ function build (options) {
|
|
|
424
477
|
// Everything that need to be encapsulated must be handled in this function.
|
|
425
478
|
function override (old, fn, opts) {
|
|
426
479
|
const shouldSkipOverride = pluginUtils.registerPlugin.call(old, fn)
|
|
480
|
+
|
|
427
481
|
if (shouldSkipOverride) {
|
|
482
|
+
// after every plugin registration we will enter a new name
|
|
483
|
+
old[kPluginNameChain].push(pluginUtils.getDisplayName(fn))
|
|
428
484
|
return old
|
|
429
485
|
}
|
|
430
486
|
|
|
@@ -441,12 +497,17 @@ function override (old, fn, opts) {
|
|
|
441
497
|
instance[kSchemas] = buildSchemas(old[kSchemas])
|
|
442
498
|
instance.getSchemas = instance[kSchemas].getSchemas.bind(instance[kSchemas])
|
|
443
499
|
instance[pluginUtils.registeredPlugins] = Object.create(instance[pluginUtils.registeredPlugins])
|
|
500
|
+
instance[kPluginNameChain] = [pluginUtils.getPluginName(fn) || pluginUtils.getFuncPreview(fn)]
|
|
501
|
+
|
|
502
|
+
if (instance[kLogSerializers] || opts.logSerializers) {
|
|
503
|
+
instance[kLogSerializers] = Object.assign(Object.create(instance[kLogSerializers]), opts.logSerializers)
|
|
504
|
+
}
|
|
444
505
|
|
|
445
506
|
if (opts.prefix) {
|
|
446
507
|
instance[kFourOhFour].arrange404(instance)
|
|
447
508
|
}
|
|
448
509
|
|
|
449
|
-
for (const hook of instance[kGlobalHooks].onRegister) hook.call(this, instance)
|
|
510
|
+
for (const hook of instance[kGlobalHooks].onRegister) hook.call(this, instance, opts)
|
|
450
511
|
|
|
451
512
|
return instance
|
|
452
513
|
}
|