UNPKG

24.2 kBMarkdownView Raw
1<h1 align="center">Fastify</h1>
2
3<a name="factory"></a>
4## Factory
5
6The Fastify module exports a factory function that is used to create new
7<a href="https://github.com/fastify/fastify/blob/master/docs/Server.md"><code><b>Fastify server</b></code></a>
8instances. This factory function accepts an options object which is used to
9customize the resulting instance. This document describes the properties
10available in that options object.
11
12<a name="factory-http2"></a>
13### `http2`
14
15If `true` Node.js core's [HTTP/2](https://nodejs.org/dist/latest-v8.x/docs/api/http2.html) module is used for binding the socket.
16
17+ Default: `false`
18
19<a name="factory-https"></a>
20### `https`
21
22An object used to configure the server's listening socket for TLS. The options
23are the same as the Node.js core
24[`createServer` method](https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_createserver_options_requestlistener).
25When this property is `null`, the socket will not be configured for TLS.
26
27This option also applies when the
28<a href="https://github.com/fastify/fastify/blob/master/docs/Server.md#factory-http2">
29<code><b>http2</b></code>
30</a> option is set.
31
32+ Default: `null`
33
34<a name="factory-ignore-slash"></a>
35### `ignoreTrailingSlash`
36
37Fastify uses [find-my-way](https://github.com/delvedor/find-my-way) to handle
38routing. This option may be set to `true` to ignore trailing slashes in routes.
39This option applies to *all* route registrations for the resulting server
40instance.
41
42+ Default: `false`
43
44```js
45const fastify = require('fastify')({
46 ignoreTrailingSlash: true
47})
48
49// registers both "/foo" and "/foo/"
50fastify.get('/foo/', function (req, reply) {
51 reply.send('foo')
52})
53
54// registers both "/bar" and "/bar/"
55fastify.get('/bar', function (req, reply) {
56 reply.send('bar')
57})
58```
59
60<a name="factory-max-param-length"></a>
61### `maxParamLength`
62You can set a custom length for parameters in parametric (standard, regex and multi) routes by using `maxParamLength` option, the default value is 100 characters.<br>
63This can be useful especially if you have some regex based route, protecting you against [DoS attacks](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS).<br>
64*If the maximum length limit is reached, the not found route will be invoked.*
65
66<a name="factory-body-limit"></a>
67### `bodyLimit`
68
69Defines the maximum payload, in bytes, the server is allowed to accept.
70
71+ Default: `1048576` (1MiB)
72
73<a name="factory-on-proto-poisoning"></a>
74### `onProtoPoisoning`
75
76Defines what action the framework must take when parsing a JSON object
77with `__proto__`. This functionality is provided by
78[bourne](https://github.com/hapijs/bourne).
79See https://hueniverse.com/a-tale-of-prototype-poisoning-2610fa170061
80for more details about prototype poisoning attacks.
81
82Possible values are `'error'`, `'remove'` and `'ignore'`.
83
84+ Default: `'error'`
85
86<a name="factory-logger"></a>
87### `logger`
88
89Fastify includes built-in logging via the [Pino](https://getpino.io/) logger.
90This property is used to configure the internal logger instance.
91
92The possible values this property may have are:
93
94+ Default: `false`. The logger is disabled. All logging methods will point to a
95null logger [abstract-logging](https://npm.im/abstract-logging) instance.
96
97+ `pinoInstance`: a previously instantiated instance of Pino. The internal
98logger will point to this instance.
99
100+ `object`: a standard Pino [options object](https://github.com/pinojs/pino/blob/c77d8ec5ce/docs/API.md#constructor).
101This will be passed directly to the Pino constructor. If the following properties
102are not present on the object, they will be added accordingly:
103 * `genReqId`: a synchronous function that will be used to generate identifiers
104 for incoming requests. The default function generates sequential identifiers.
105 * `level`: the minimum logging level. If not set, it will be set to `'info'`.
106 * `serializers`: a hash of serialization functions. By default, serializers
107 are added for `req` (incoming request objects), `res` (outgoing repsonse
108 objets), and `err` (standard `Error` objects). When a log method receives
109 an object with any of these properties then the respective serializer will
110 be used for that property. For example:
111 ```js
112 fastify.get('/foo', function (req, res) {
113 req.log.info({req}) // log the serialized request object
114 res.send('foo')
115 })
116 ```
117 Any user supplied serializer will override the default serializer of the
118 corresponding property.
119+ `loggerInstance`: a custom logger instance. The logger must conform to the Pino
120interface by having the following methods: `info`, `error`, `debug`, `fatal`, `warn`, `trace`, `child`. For example:
121 ```js
122 const pino = require('pino')();
123
124 const customLogger = {
125 info: function (o, ...n) {},
126 warn: function (o, ...n) {},
127 error: function (o, ...n) {},
128 fatal: function (o, ...n) {},
129 trace: function (o, ...n) {},
130 debug: function (o, ...n) {},
131 child: function() {
132 const child = Object.create(this);
133 child.pino = pino.child(...arguments);
134 return child;
135 },
136 };
137
138 const fastify = require('fastify')({logger: customLogger});
139 ```
140
141<a name="custom-http-server"></a>
142### `serverFactory`
143You can pass a custom http server to Fastify by using the `serverFactory` option.<br/>
144`serverFactory` is a function that takes an `handler` parameter, which takes the `request` and `response` objects as parameters, and an options object, which is the same you have passed to Fastify.
145
146```js
147const serverFactory = (handler, opts) => {
148 const server = http.createServer((req, res) => {
149 handler(req, res)
150 })
151
152 return server
153}
154
155const fastify = Fastify({ serverFactory, modifyCoreObjects: false })
156
157fastify.get('/', (req, reply) => {
158 reply.send({ hello: 'world' })
159})
160
161fastify.listen(3000)
162```
163
164Internally Fastify uses the API of Node core http server, so if you are using a custom server you must be sure to have the same API exposed. If not, you can enhance the server instance inside the `serverFactory` function before the `return` statement.<br/>
165*Note that we have also added `modifyCoreObjects: false` because in some serverless environments such as Google Cloud Functions, some Node.js core properties are not writable.*
166
167<a name="factory-case-sensitive"></a>
168### `caseSensitive`
169
170By default, value equal to `true`, routes are registered as case sensitive. That is, `/foo` is not equivalent to `/Foo`. When set to `false`, routes are registered in a fashion such that `/foo` is equivalent to `/Foo` which is equivalent to `/FOO`.
171
172By setting `caseSensitive` to `false`, all paths will be matched as lowercase, but the route parameters or wildcards will maintain their original letter casing.
173
174```js
175fastify.get('/user/:username', (request, reply) => {
176 // Given the URL: /USER/NodeJS
177 console.log(request.params.username) // -> 'NodeJS'
178})
179```
180
181Please note this setting this option to `false` goes against
182[RFC3986](https://tools.ietf.org/html/rfc3986#section-6.2.2.1).
183
184<a name="factory-request-id-header"></a>
185### `requestIdHeader`
186
187The header name used to know the request id. See [the request id](https://github.com/fastify/fastify/blob/master/docs/Logging.md#logging-request-id) section.
188
189+ Default: `'request-id'`
190
191<a name="factory-request-id-log-label"></a>
192### `requestIdLogLabel`
193
194Defines the label used for the request identifier when logging the request.
195
196+ Default: `'reqId'`
197
198<a name="factory-gen-request-id"></a>
199### `genReqId`
200
201Function for generating the request id. It will receive the incoming request as a parameter.
202
203+ Default: `value of 'request-id' if provided or monotonically increasing integers`
204
205Especially in distributed systems, you may want to override the default id generation behaviour as shown below. For generating `UUID`s you may want to checkout [hyperid](https://github.com/mcollina/hyperid)
206
207```js
208let i = 0
209const fastify = require('fastify')({
210 genReqId: function (req) { return req.headers['request-id'] || i++ }
211})
212```
213
214**Note: genReqId will _not_ be called if the 'request-id' header is available.**
215
216<a name="factory-trust-proxy"></a>
217### `trustProxy`
218
219By enabling the `trustProxy` option, Fastify will have knowledge that it's sitting behind a proxy and that the `X-Forwarded-*` header fields may be trusted, which otherwise may be easily spoofed.
220
221```js
222const fastify = Fastify({ trustProxy: true })
223```
224
225+ Default: `false`
226+ `true/false`: Trust all proxies (`true`) or do not trust any proxies (`false`).
227+ `string`: Trust only given IP/CIDR (e.g. `'127.0.0.1'`). May be a list of comma separated values (e.g. `'127.0.0.1,192.168.1.1/24'`).
228+ `Array<string>`: Trust only given IP/CIDR list (e.g. `['127.0.0.1']`).
229+ `number`: Trust the nth hop from the front-facing proxy server as the client.
230+ `Function`: Custom trust function that takes `address` as first arg
231 ```js
232 function myTrustFn(address, hop) {
233 return address === '1.2.3.4' || hop === 1
234 }
235 ```
236
237For more examples refer to [proxy-addr](https://www.npmjs.com/package/proxy-addr) package.
238
239You may access the `ip`, `ips`, and `hostname` values on the [`request`](https://github.com/fastify/fastify/blob/master/docs/Request.md) object.
240
241```js
242fastify.get('/', (request, reply) => {
243 console.log(request.ip)
244 console.log(request.ips)
245 console.log(request.hostname)
246})
247```
248
249<a name="plugin-timeout"></a>
250### `pluginTimeout`
251
252The maximum amount of time in *milliseconds* in which a plugin can load.
253If not, [`ready`](https://github.com/fastify/fastify/blob/master/docs/Server.md#ready)
254will complete with an `Error` with code `'ERR_AVVIO_PLUGIN_TIMEOUT'`.
255
256+ Default: `10000`
257
258<a name="factory-querystring-parser"></a>
259### `querystringParser`
260
261The default query string parser that Fastify uses is the Node.js's core `querystring` module.<br/>
262You can change this default setting by passing the option `querystringParser` and use a custom one, such as [`qs`](https://www.npmjs.com/package/qs).
263
264```js
265const qs = require('qs')
266const fastify = require('fastify')({
267 querystringParser: str => qs.parse(str)
268})
269```
270
271<a name="versioning"></a>
272### `versioning`
273
274By default you can version your routes with [semver versioning](https://github.com/fastify/fastify/blob/master/docs/Routes.md#version), which is provided by `find-my-way`. There is still an option to provide custom versioning strategy. You can find more information in the [find-my-way](https://github.com/delvedor/find-my-way#versioned-routes) documentation.
275
276```js
277const versioning = {
278 storage: function () {
279 let versions = {}
280 return {
281 get: (version) => { return versions[version] || null },
282 set: (version, store) => { versions[version] = store },
283 del: (version) => { delete versions[version] },
284 empty: () => { versions = {} }
285 }
286 },
287 deriveVersion: (req, ctx) => {
288 return req.headers['accept']
289 }
290}
291
292const fastify = require('fastify')({
293 versioning
294})
295```
296
297<a name="factory-modify-core-objects"></a>
298### `modifyCoreObjects`
299
300+ Default: `true`
301
302By default, Fastify will add the `ip`, `ips`, `hostname`, and `log` properties to Node's raw request object (see [`Request`](https://github.com/fastify/fastify/blob/master/docs/Request.md)) and the `log` property to Node's raw response object. Set to `false` to prevent these properties from being added to the Node core objects.
303
304```js
305const fastify = Fastify({ modifyCoreObjects: true }) // the default
306
307fastify.get('/', (request, reply) => {
308 console.log(request.raw.ip)
309 console.log(request.raw.ips)
310 console.log(request.raw.hostname)
311 request.raw.log('Hello')
312 reply.res.log('World')
313})
314```
315
316Disable this option could help in serverless environments such as Google Cloud Functions, where `ip` and `ips` are not writable properties.
317
318**Note that these properties are deprecated and will be removed in the next major version of Fastify along with this option.** It is recommended to use the same properties on Fastify's [`Request`](https://github.com/fastify/fastify/blob/master/docs/Request.md) and [`Reply`](https://github.com/fastify/fastify/blob/master/docs/Reply.md) objects instead.
319
320```js
321const fastify = Fastify({ modifyCoreObjects: false })
322
323fastify.get('/', (request, reply) => {
324 console.log(request.ip)
325 console.log(request.ips)
326 console.log(request.hostname)
327 request.log('Hello')
328 reply.log('World')
329})
330```
331
332## Instance
333
334### Server Methods
335
336<a name="server"></a>
337#### server
338`fastify.server`: The Node core [server](https://nodejs.org/api/http.html#http_class_http_server) object as returned by the [**`Fastify factory function`**](https://github.com/fastify/fastify/blob/master/docs/Server.md).
339
340<a name="after"></a>
341#### after
342Invoked when the current plugin and all the plugins
343that have been registered within it have finished loading.
344It is always executed before the method `fastify.ready`.
345
346```js
347fastify
348 .register((instance, opts, next) => {
349 console.log('Current plugin')
350 next()
351 })
352 .after(err => {
353 console.log('After current plugin')
354 })
355 .register((instance, opts, next) => {
356 console.log('Next plugin')
357 next()
358 })
359 .ready(err => {
360 console.log('Everything has been loaded')
361 })
362```
363
364<a name="ready"></a>
365#### ready
366Function called when all the plugins have been loaded.
367It takes an error parameter if something went wrong.
368```js
369fastify.ready(err => {
370 if (err) throw err
371})
372```
373If it is called without any arguments, it will return a `Promise`:
374
375```js
376fastify.ready().then(() => {
377 console.log('successfully booted!')
378}, (err) => {
379 console.log('an error happened', err)
380})
381```
382
383<a name="listen"></a>
384#### listen
385Starts the server on the given port after all the plugins are loaded, internally waits for the `.ready()` event. The callback is the same as the Node core. By default, the server will listen on the address resolved by `localhost` when no specific address is provided (`127.0.0.1` or `::1` depending on the operating system). If listening on any available interface is desired, then specifying `0.0.0.0` for the address will listen on all IPv4 address. Using `::` for the address will listen on all IPv6 addresses, and, depending on OS, may also listen on all IPv4 addresses. Be careful when deciding to listen on all interfaces; it comes with inherent [security risks](https://web.archive.org/web/20170831174611/https://snyk.io/blog/mongodb-hack-and-secure-defaults/).
386
387```js
388fastify.listen(3000, (err, address) => {
389 if (err) {
390 fastify.log.error(err)
391 process.exit(1)
392 }
393})
394```
395
396Specifying an address is also supported:
397
398```js
399fastify.listen(3000, '127.0.0.1', (err, address) => {
400 if (err) {
401 fastify.log.error(err)
402 process.exit(1)
403 }
404})
405```
406
407Specifying a backlog queue size is also supported:
408
409```js
410fastify.listen(3000, '127.0.0.1', 511, (err, address) => {
411 if (err) {
412 fastify.log.error(err)
413 process.exit(1)
414 }
415})
416```
417
418Specifying options is also supported, the object is same as [options](https://nodejs.org/api/net.html#net_server_listen_options_callback) in the Node.js server listen:
419
420```js
421fastify.listen({ port: 3000, host: '127.0.0.1', backlog: 511 }, (err) => {
422 if (err) {
423 fastify.log.error(err)
424 process.exit(1)
425 }
426})
427```
428
429If no callback is provided a Promise is returned:
430
431```js
432fastify.listen(3000)
433 .then((address) => console.log(`server listening on ${address}`))
434 .catch(err => {
435 console.log('Error starting server:', err)
436 process.exit(1)
437 })
438```
439
440Specifying an address without a callback is also supported:
441
442```js
443fastify.listen(3000, '127.0.0.1')
444 .then((address) => console.log(`server listening on ${address}`))
445 .catch(err => {
446 console.log('Error starting server:', err)
447 process.exit(1)
448 })
449```
450
451Specifying options without a callback is also supported:
452
453```js
454fastify.listen({ port: 3000, host: '127.0.0.1', backlog: 511 })
455 .then((address) => console.log(`server listening on ${address}`))
456 .catch(err => {
457 console.log('Error starting server:', err)
458 process.exit(1)
459 })
460```
461
462When deploying to a Docker, and potentially other, containers, it is advisable to listen on `0.0.0.0` because they do not default to exposing mapped ports to `localhost`:
463
464```js
465fastify.listen(3000, '0.0.0.0', (err, address) => {
466 if (err) {
467 fastify.log.error(err)
468 process.exit(1)
469 }
470})
471```
472
473If the `port` is omitted (or is set to zero), a random available port is automatically chosen (later available via `fastify.server.address().port`).
474
475The default options of listen are:
476
477```js
478fastify.listen({
479 port: 0,
480 host: 'localhost',
481 exclusive: false,
482 readableAll: false,
483 writableAll: false,
484 ipv6Only: false
485}, (err) => {})
486```
487
488<a name="route"></a>
489#### route
490Method to add routes to the server, it also has shorthand functions, check [here](https://github.com/fastify/fastify/blob/master/docs/Routes.md).
491
492<a name="close"></a>
493#### close
494`fastify.close(callback)`: call this function to close the server instance and run the [`'onClose'`](https://github.com/fastify/fastify/blob/master/docs/Hooks.md#on-close) hook.<br>
495Calling `close` will also cause the server to respond to every new incoming request with a `503` error and destroy that request.
496
497<a name="decorate"></a>
498#### decorate*
499Function useful if you need to decorate the fastify instance, Reply or Request, check [here](https://github.com/fastify/fastify/blob/master/docs/Decorators.md).
500
501<a name="register"></a>
502#### register
503Fastify allows the user to extend its functionality with plugins.
504A plugin can be a set of routes, a server decorator or whatever, check [here](https://github.com/fastify/fastify/blob/master/docs/Plugins.md).
505
506<a name="use"></a>
507#### use
508Function to add middlewares to Fastify, check [here](https://github.com/fastify/fastify/blob/master/docs/Middlewares.md).
509
510<a name="addHook"></a>
511#### addHook
512Function to add a specific hook in the lifecycle of Fastify, check [here](https://github.com/fastify/fastify/blob/master/docs/Hooks.md).
513
514<a name="prefix"></a>
515#### prefix
516The full path that will be prefixed to a route.
517
518Example:
519
520```js
521fastify.register(function (instance, opts, next) {
522 instance.get('/foo', function (request, reply) {
523 // Will log "prefix: /v1"
524 request.log.info('prefix: %s', instance.prefix)
525 reply.send({ prefix: instance.prefix })
526 })
527
528 instance.register(function (instance, opts, next) {
529 instance.get('/bar', function (request, reply) {
530 // Will log "prefix: /v1/v2"
531 request.log.info('prefix: %s', instance.prefix)
532 reply.send({ prefix: instance.prefix })
533 })
534
535 next()
536 }, { prefix: '/v2' })
537
538 next()
539}, { prefix: '/v1' })
540```
541
542<a name="log"></a>
543#### log
544The logger instance, check [here](https://github.com/fastify/fastify/blob/master/docs/Logging.md).
545
546<a name="inject"></a>
547#### inject
548Fake http injection (for testing purposes) [here](https://github.com/fastify/fastify/blob/master/docs/Testing.md#inject).
549
550<a name="add-schema"></a>
551#### addSchema
552`fastify.addSchema(schemaObj)`, adds a shared schema to the Fastify instance. This allows you to reuse it everywhere in your application just by writing the schema id that you need.<br/>
553To learn more, see [shared schema example](https://github.com/fastify/fastify/blob/master/docs/Validation-and-Serialization.md#shared-schema) in the [Validation and Serialization](https://github.com/fastify/fastify/blob/master/docs/Validation-and-Serialization.md) documentation.
554
555<a name="set-schema-compiler"></a>
556#### setSchemaCompiler
557Set the schema compiler for all routes [here](https://github.com/fastify/fastify/blob/master/docs/Validation-and-Serialization.md#schema-compiler).
558
559<a name="schema-compiler"></a>
560#### schemaCompiler
561This property can be used to set the schema compiler, it is a shortcut for the `setSchemaCompiler` method, and get the schema compiler back for all routes.
562
563<a name="set-not-found-handler"></a>
564#### setNotFoundHandler
565
566`fastify.setNotFoundHandler(handler(request, reply))`: set the 404 handler. This call is encapsulated by prefix, so different plugins can set different not found handlers if a different [`prefix` option](https://github.com/fastify/fastify/blob/master/docs/Plugins.md#route-prefixing-option) is passed to `fastify.register()`. The handler is treated like a regular route handler so requests will go through the full [Fastify lifecycle](https://github.com/fastify/fastify/blob/master/docs/Lifecycle.md#lifecycle).
567
568You can also register a [`preValidation`](https://www.fastify.io/docs/latest/Hooks/#route-hooks) and [preHandler](https://www.fastify.io/docs/latest/Hooks/#route-hooks) hook for the 404 handler.
569
570```js
571fastify.setNotFoundHandler({
572 preValidation: (req, reply, next) => {
573 // your code
574 next()
575 },
576 preHandler: (req, reply, next) => {
577 // your code
578 next()
579 }
580}, function (request, reply) {
581 // Default not found handler with preValidation and preHandler hooks
582})
583
584fastify.register(function (instance, options, next) {
585 instance.setNotFoundHandler(function (request, reply) {
586 // Handle not found request without preValidation and preHandler hooks
587 // to URLs that begin with '/v1'
588 })
589 next()
590}, { prefix: '/v1' })
591```
592
593<a name="set-error-handler"></a>
594#### setErrorHandler
595
596`fastify.setErrorHandler(handler(error, request, reply))`: Set a function that will be called whenever an error happens. The handler is fully encapsulated, so different plugins can set different error handlers. *async-await* is supported as well.<br>
597*Note: If the error `statusCode` is less than 400, Fastify will automatically set it at 500 before calling the error handler.*
598
599```js
600fastify.setErrorHandler(function (error, request, reply) {
601 // Log error
602 // Send error response
603})
604```
605
606Fastify is provided with a default function that is called if no error handler is set and that logs the error with respect to its `statusCode`:
607
608```js
609var statusCode = error.statusCode
610if (statusCode >= 500) {
611 log.error(error)
612} else if (statusCode >= 400) {
613 log.info(error)
614} else {
615 log.error(error)
616}
617```
618
619<a name="print-routes"></a>
620#### printRoutes
621
622`fastify.printRoutes()`: Prints the representation of the internal radix tree used by the router, useful for debugging.<br/>
623*Remember to call it inside or after a `ready` call.*
624
625```js
626fastify.get('/test', () => {})
627fastify.get('/test/hello', () => {})
628fastify.get('/hello/world', () => {})
629
630fastify.ready(() => {
631 console.log(fastify.printRoutes())
632 // └── /
633 // ├── test (GET)
634 // │ └── /hello (GET)
635 // └── hello/world (GET)
636})
637```
638
639<a name="initial-config"></a>
640#### initialConfig
641
642`fastify.initialConfig`: Exposes a frozen read-only object registering the initial
643options passed down by the user to the fastify instance.
644
645Currently the properties that can be exposed are:
646- bodyLimit
647- caseSensitive
648- http2
649- https (it will return `false`/`true` or `{ allowHTTP1: true/false }` if explicitly passed)
650- ignoreTrailingSlash
651- maxParamLength
652- onProtoPoisoning
653- pluginTimeout
654- requestIdHeader
655
656```js
657const { readFileSync } = require('fs')
658const Fastify = require('fastify')
659
660const fastify = Fastify({
661 https: {
662 allowHTTP1: true,
663 key: readFileSync('./fastify.key'),
664 cert: readFileSync('./fastify.cert')
665 },
666 logger: { level: 'trace'},
667 ignoreTrailingSlash: true,
668 maxParamLength: 200,
669 caseSensitive: true,
670 trustProxy: '127.0.0.1,192.168.1.1/24',
671})
672
673console.log(fastify.initialConfig)
674/*
675will log :
676{
677 caseSensitive: true,
678 https: { allowHTTP1: true },
679 ignoreTrailingSlash: true,
680 maxParamLength: 200
681}
682*/
683
684fastify.register(async (instance, opts) => {
685 instance.get('/', async (request, reply) => {
686 return instance.initialConfig
687 /*
688 will return :
689 {
690 caseSensitive: true,
691 https: { allowHTTP1: true },
692 ignoreTrailingSlash: true,
693 maxParamLength: 200
694 }
695 */
696 })
697
698 instance.get('/error', async (request, reply) => {
699 // will throw an error because initialConfig is read-only
700 // and can not be modified
701 instance.initialConfig.https.allowHTTP1 = false
702
703 return instance.initialConfig
704 })
705})
706
707// Start listening.
708fastify.listen(3000, (err) => {
709 if (err) {
710 fastify.log.error(err)
711 process.exit(1)
712 }
713})
714```