fastify
Version:
Fast and low overhead web framework, for Node.js
532 lines (415 loc) • 18.9 kB
Markdown
<h1 align="center">Fastify</h1>
<a name="factory"></a>
## Factory
The Fastify module exports a factory function that is used to create new
<a href="https://github.com/fastify/fastify/blob/master/docs/Server.md"><code><b>Fastify server</b></code></a>
instances. This factory function accepts an options object which is used to
customize the resulting instance. This document describes the properties
available in that options object.
<a name="factory-http2"></a>
### `http2` (Status: experimental)
If `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.
+ Default: `false`
<a name="factory-https"></a>
### `https`
An object used to configure the server's listening socket for TLS. The options
are the same as the Node.js core
[`createServer` method](https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_createserver_options_requestlistener).
When this property is `null`, the socket will not be configured for TLS.
This option also applies when the
<a href="https://github.com/fastify/fastify/blob/master/docs/Server.md#factory-http2">
<code><b>http2</b></code>
</a> option is set.
+ Default: `null`
<a name="factory-ignore-slash"></a>
### `ignoreTrailingSlash`
Fastify uses [find-my-way](https://github.com/delvedor/find-my-way) to handle
routing. This option may be set to `true` to ignore trailing slashes in routes.
This option applies to *all* route registrations for the resulting server
instance.
+ Default: `false`
```js
const fastify = require('fastify')({
ignoreTrailingSlash: true
})
// registers both "/foo" and "/foo/"
fastify.get('/foo/', function (req, reply) {
res.send('foo')
})
// registers both "/bar" and "/bar/"
fastify.get('/bar', function (req, reply) {
res.send('bar')
})
```
<a name="factory-max-param-length"></a>
### `maxParamLength`
You 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>
This 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>
*If the maximum length limit is reached, the not found route will be invoked.*
<a name="factory-body-limit"></a>
### `bodyLimit`
Defines the maximum payload, in bytes, the server is allowed to accept.
+ Default: `1048576` (1MiB)
<a name="factory-on-proto-poisoning"></a>
### `onProtoPoisoning`
Defines what action the framework must take when parsing a JSON object
with `__proto__`. This functionality is provided by
[bourne](https://github.com/hapijs/bourne).
See https://hueniverse.com/a-tale-of-prototype-poisoning-2610fa170061
for more details about prototype poisoning attacks.
Possible values are `'error'`, `'remove'` and `'ignore'`.
+ Default: `'error'`
<a name="factory-logger"></a>
### `logger`
Fastify includes built-in logging via the [Pino](https://getpino.io/) logger.
This property is used to configure the internal logger instance.
The possible values this property may have are:
+ Default: `false`. The logger is disabled. All logging methods will point to a
null logger [abstract-logging](https://npm.im/abstract-logging) instance.
+ `pinoInstance`: a previously instantiated instance of Pino. The internal
logger will point to this instance.
+ `object`: a standard Pino [options object](https://github.com/pinojs/pino/blob/c77d8ec5ce/docs/API.md#constructor).
This will be passed directly to the Pino constructor. If the following properties
are not present on the object, they will be added accordingly:
* `genReqId`: a synchronous function that will be used to generate identifiers
for incoming requests. The default function generates sequential identifiers.
* `level`: the minimum logging level. If not set, it will be set to `'info'`.
* `serializers`: a hash of serialization functions. By default, serializers
are added for `req` (incoming request objects), `res` (outgoing repsonse
objets), and `err` (standard `Error` objects). When a log method receives
an object with any of these properties then the respective serializer will
be used for that property. For example:
```js
fastify.get('/foo', function (req, res) {
req.log.info({req}) // log the serialized request object
res.send('foo')
})
```
Any user supplied serializer will override the default serializer of the
corresponding property.
<a name="custom-http-server"></a>
### `serverFactory`
You can pass a custom http server to Fastify by using the `serverFactory` option.<br/>
`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.
```js
const serverFactory = (handler, opts) => {
const server = http.createServer((req, res) => {
handler(req, res)
})
return server
}
const fastify = Fastify({ serverFactory })
fastify.get('/', (req, reply) => {
reply.send({ hello: 'world' })
})
fastify.listen(3000)
```
Internally 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.
<a name="factory-case-sensitive"></a>
### `caseSensitive`
By 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`.
By setting `caseSensitive` to `false`, all paths will be matched as lowercase, but the route parameters or wildcards will maintain their original letter casing.
```js
fastify.get('/user/:username', (request, reply) => {
// Given the URL: /USER/NodeJS
console.log(request.params.username) // -> 'NodeJS'
})
```
Please note this setting this option to `false` goes against
[RFC3986](https://tools.ietf.org/html/rfc3986#section-6.2.2.1).
<a name="factory-request-id-header"></a>
### `requestIdHeader`
The 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.
+ Default: `'request-id'`
<a name="factory-gen-request-id"></a>
### `genReqId`
Function for generating the request id. It will receive the incoming request as a parameter.
+ Default: `value of 'request-id' if provided or monotonically increasing integers`
Especially 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)
```js
let i = 0
const fastify = require('fastify')({
genReqId: function (req) { return i++ }
})
```
<a name="factory-trust-proxy"></a>
### `trustProxy`
By 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.
```js
const fastify = Fastify({ trustProxy: true })
```
+ Default: `false`
+ `true/false`: Trust all proxies (`true`) or do not trust any proxies (`false`).
+ `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'`).
+ `Array<string>`: Trust only given IP/CIDR list (e.g. `['127.0.0.1']`).
+ `number`: Trust the nth hop from the front-facing proxy server as the client.
+ `Function`: Custom trust function that takes `address` as first arg
```js
function myTrustFn(address, hop) {
return address === '1.2.3.4' || hop === 1
}
```
For more examples refer to [proxy-addr](https://www.npmjs.com/package/proxy-addr) package.
You may also access `ip` and `hostname` values from raw `request`.
```js
fastify.get('/', (request, reply) => {
console.log(request.raw.ip)
console.log(request.raw.hostname)
})
```
<a name="plugin-timeout"></a>
### `pluginTimeout`
The maximum amount of time in *milliseconds* in which a plugin can load.
If not, [`ready`](https://github.com/fastify/fastify/blob/master/docs/Server.md#ready)
will complete with an `Error` with code `'ERR_AVVIO_PLUGIN_TIMEOUT'`.
+ Default: `10000`
<a name="factory-querystring-parser"></a>
### `querystringParser`
The default query string parser that Fastify uses is the Node.js's core `querystring` module.<br/>
You can change this default setting by passing the option `querystringParser` and use a custom one, such as [`qs`](https://www.npmjs.com/package/qs).
```js
const qs = require('qs')
const fastify = require('fastify')({
querystringParser: str => qs.parse(str)
})
```
<a name="versioning"></a>
### `versioning`
By 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.
```js
const versioning = {
storage: function () {
let versions = {}
return {
get: (version) => { return versions[version] || null },
set: (version, store) => { versions[version] = store },
del: (version) => { delete versions[version] },
empty: () => { versions = {} }
}
},
deriveVersion: (req, ctx) => {
return req.headers['accept']
}
}
const fastify = require('fastify')({
versioning
})
```
## Instance
### Server Methods
<a name="server"></a>
#### server
`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).
<a name="after"></a>
#### after
Invoked when the current plugin and all the plugins
that have been registered within it have finished loading.
It is always executed before the method `fastify.ready`.
```js
fastify
.register((instance, opts, next) => {
console.log('Current plugin')
next()
})
.after(err => {
console.log('After current plugin')
})
.register((instance, opts, next) => {
console.log('Next plugin')
next()
})
.ready(err => {
console.log('Everything has been loaded')
})
```
<a name="ready"></a>
#### ready
Function called when all the plugins have been loaded.
It takes an error parameter if something went wrong.
```js
fastify.ready(err => {
if (err) throw err
})
```
If it is called without any arguments, it will return a `Promise`:
```js
fastify.ready().then(() => {
console.log('successfully booted!')
}, (err) => {
console.log('an error happened', err)
})
```
<a name="listen"></a>
#### listen
Starts 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/).
```js
fastify.listen(3000, (err, address) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
```
Specifying an address is also supported:
```js
fastify.listen(3000, '127.0.0.1', (err, address) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
```
Specifying a backlog queue size is also supported:
```js
fastify.listen(3000, '127.0.0.1', 511, (err, address) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
```
If no callback is provided a Promise is returned:
```js
fastify.listen(3000)
.then((address) => console.log(`server listening on ${address}`))
.catch(err => {
console.log('Error starting server:', err)
process.exit(1)
})
```
Specifying an address without a callback is also supported:
```js
fastify.listen(3000, '127.0.0.1')
.then((address) => console.log(`server listening on ${address}`))
.catch(err => {
console.log('Error starting server:', err)
process.exit(1)
})
```
When 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`:
```js
fastify.listen(3000, '0.0.0.0', (err, address) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})
```
If the `port` is omitted (or is set to zero), a random available port is automatically chosen (later available via `fastify.server.address().port`).
<a name="route"></a>
#### route
Method to add routes to the server, it also has shorthand functions, check [here](https://github.com/fastify/fastify/blob/master/docs/Routes.md).
<a name="close"></a>
#### close
`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>
Calling `close` will also cause the server to respond to every new incoming request with a `503` error and destroy that request.
<a name="decorate"></a>
#### decorate*
Function useful if you need to decorate the fastify instance, Reply or Request, check [here](https://github.com/fastify/fastify/blob/master/docs/Decorators.md).
<a name="register"></a>
#### register
Fastify allows the user to extend its functionality with plugins.
A plugin can be a set of routes, a server decorator or whatever, check [here](https://github.com/fastify/fastify/blob/master/docs/Plugins.md).
<a name="use"></a>
#### use
Function to add middlewares to Fastify, check [here](https://github.com/fastify/fastify/blob/master/docs/Middlewares.md).
<a name="addHook"></a>
#### addHook
Function to add a specific hook in the lifecycle of Fastify, check [here](https://github.com/fastify/fastify/blob/master/docs/Hooks.md).
<a name="prefix"></a>
#### prefix
The full path that will be prefixed to a route.
Example:
```js
fastify.register(function (instance, opts, next) {
instance.get('/foo', function (request, reply) {
// Will log "prefix: /v1"
request.log.info('prefix: %s', instance.prefix)
reply.send({ prefix: instance.prefix })
})
instance.register(function (instance, opts, next) {
instance.get('/bar', function (request, reply) {
// Will log "prefix: /v1/v2"
request.log.info('prefix: %s', instance.prefix)
reply.send({ prefix: instance.prefix })
})
next()
}, { prefix: '/v2' })
next()
}, { prefix: '/v1' })
```
<a name="log"></a>
#### log
The logger instance, check [here](https://github.com/fastify/fastify/blob/master/docs/Logging.md).
<a name="inject"></a>
#### inject
Fake http injection (for testing purposes) [here](https://github.com/fastify/fastify/blob/master/docs/Testing.md#inject).
<a name="add-schema"></a>
#### addSchema
`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/>
To 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.
<a name="set-schema-compiler"></a>
#### setSchemaCompiler
Set the schema compiler for all routes [here](https://github.com/fastify/fastify/blob/master/docs/Validation-and-Serialization.md#schema-compiler).
<a name="set-not-found-handler"></a>
#### setNotFoundHandler
`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).
You 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.
```js
fastify.setNotFoundHandler({
preValidation: (req, reply, next) => {
// your code
next()
},
preHandler: (req, reply, next) => {
// your code
next()
}
}, function (request, reply) {
// Default not found handler with preValidation and preHandler hooks
})
fastify.register(function (instance, options, next) {
instance.setNotFoundHandler(function (request, reply) {
// Handle not found request without preValidation and preHandler hooks
// to URLs that begin with '/v1'
})
next()
}, { prefix: '/v1' })
```
<a name="set-error-handler"></a>
#### setErrorHandler
`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>
*Note: If the error `statusCode` is less than 400, Fastify will automatically set it at 500 before calling the error handler.*
```js
fastify.setErrorHandler(function (error, request, reply) {
// Log error
// Send error response
})
```
Fastify 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`:
```js
var statusCode = error.statusCode
if (statusCode >= 500) {
log.error(error)
} else if (statusCode >= 400) {
log.info(error)
} else {
log.error(error)
}
```
<a name="print-routes"></a>
#### printRoutes
`fastify.printRoutes()`: Prints the representation of the internal radix tree used by the router, useful for debugging.<br/>
*Remember to call it inside or after a `ready` call.*
```js
fastify.get('/test', () => {})
fastify.get('/test/hello', () => {})
fastify.get('/hello/world', () => {})
fastify.ready(() => {
console.log(fastify.printRoutes())
// └── /
// ├── test (GET)
// │ └── /hello (GET)
// └── hello/world (GET)
})
```