Projektstart
This commit is contained in:
246
backend/node_modules/fastify/docs/Reference/ContentTypeParser.md
generated
vendored
Normal file
246
backend/node_modules/fastify/docs/Reference/ContentTypeParser.md
generated
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## `Content-Type` Parser
|
||||
Natively, Fastify only supports `'application/json'` and `'text/plain'` content
|
||||
types. If the content type is not one of these, an
|
||||
`FST_ERR_CTP_INVALID_MEDIA_TYPE` error will be thrown.
|
||||
Other common content types are supported through the use of
|
||||
[plugins](https://fastify.dev/ecosystem/).
|
||||
|
||||
The default charset is `utf-8`. If you need to support different content types,
|
||||
you can use the `addContentTypeParser` API. *The default JSON and/or plain text
|
||||
parser can be changed or removed.*
|
||||
|
||||
*Note: If you decide to specify your own content type with the `Content-Type`
|
||||
header, UTF-8 will not be the default. Be sure to include UTF-8 like this
|
||||
`text/html; charset=utf-8`.*
|
||||
|
||||
As with the other APIs, `addContentTypeParser` is encapsulated in the scope in
|
||||
which it is declared. This means that if you declare it in the root scope it
|
||||
will be available everywhere, while if you declare it inside a plugin it will be
|
||||
available only in that scope and its children.
|
||||
|
||||
Fastify automatically adds the parsed request payload to the [Fastify
|
||||
request](./Request.md) object which you can access with `request.body`.
|
||||
|
||||
Note that for `GET` and `HEAD` requests the payload is never parsed. For
|
||||
`OPTIONS` and `DELETE` requests the payload is only parsed if the content type
|
||||
is given in the content-type header. If it is not given, the
|
||||
[catch-all](#catch-all) parser is not executed as with `POST`, `PUT` and
|
||||
`PATCH`, but the payload is simply not parsed.
|
||||
|
||||
### Usage
|
||||
```js
|
||||
fastify.addContentTypeParser('application/jsoff', function (request, payload, done) {
|
||||
jsoffParser(payload, function (err, body) {
|
||||
done(err, body)
|
||||
})
|
||||
})
|
||||
|
||||
// Handle multiple content types with the same function
|
||||
fastify.addContentTypeParser(['text/xml', 'application/xml'], function (request, payload, done) {
|
||||
xmlParser(payload, function (err, body) {
|
||||
done(err, body)
|
||||
})
|
||||
})
|
||||
|
||||
// Async is also supported in Node versions >= 8.0.0
|
||||
fastify.addContentTypeParser('application/jsoff', async function (request, payload) {
|
||||
var res = await jsoffParserAsync(payload)
|
||||
|
||||
return res
|
||||
})
|
||||
|
||||
// Handle all content types that matches RegExp
|
||||
fastify.addContentTypeParser(/^image\/.*/, function (request, payload, done) {
|
||||
imageParser(payload, function (err, body) {
|
||||
done(err, body)
|
||||
})
|
||||
})
|
||||
|
||||
// Can use default JSON/Text parser for different content Types
|
||||
fastify.addContentTypeParser('text/json', { parseAs: 'string' }, fastify.getDefaultJsonParser('ignore', 'ignore'))
|
||||
```
|
||||
|
||||
Fastify first tries to match a content-type parser with a `string` value before
|
||||
trying to find a matching `RegExp`. If you provide overlapping content types,
|
||||
Fastify tries to find a matching content type by starting with the last one
|
||||
passed and ending with the first one. So if you want to specify a general
|
||||
content type more precisely, first specify the general content type and then the
|
||||
more specific one, like in the example below.
|
||||
|
||||
```js
|
||||
// Here only the second content type parser is called because its value also matches the first one
|
||||
fastify.addContentTypeParser('application/vnd.custom+xml', (request, body, done) => {} )
|
||||
fastify.addContentTypeParser('application/vnd.custom', (request, body, done) => {} )
|
||||
|
||||
// Here the desired behavior is achieved because fastify first tries to match the
|
||||
// `application/vnd.custom+xml` content type parser
|
||||
fastify.addContentTypeParser('application/vnd.custom', (request, body, done) => {} )
|
||||
fastify.addContentTypeParser('application/vnd.custom+xml', (request, body, done) => {} )
|
||||
```
|
||||
|
||||
Besides the `addContentTypeParser` API there are further APIs that can be used.
|
||||
These are `hasContentTypeParser`, `removeContentTypeParser` and
|
||||
`removeAllContentTypeParsers`.
|
||||
|
||||
#### hasContentTypeParser
|
||||
|
||||
You can use the `hasContentTypeParser` API to find if a specific content type
|
||||
parser already exists.
|
||||
|
||||
```js
|
||||
if (!fastify.hasContentTypeParser('application/jsoff')){
|
||||
fastify.addContentTypeParser('application/jsoff', function (request, payload, done) {
|
||||
jsoffParser(payload, function (err, body) {
|
||||
done(err, body)
|
||||
})
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
#### removeContentTypeParser
|
||||
|
||||
With `removeContentTypeParser` a single or an array of content types can be
|
||||
removed. The method supports `string` and `RegExp` content types.
|
||||
|
||||
```js
|
||||
fastify.addContentTypeParser('text/xml', function (request, payload, done) {
|
||||
xmlParser(payload, function (err, body) {
|
||||
done(err, body)
|
||||
})
|
||||
})
|
||||
|
||||
// Removes the both built-in content type parsers so that only the content type parser for text/html is available
|
||||
fastify.removeContentTypeParser(['application/json', 'text/plain'])
|
||||
```
|
||||
|
||||
#### removeAllContentTypeParsers
|
||||
|
||||
In the example from just above, it is noticeable that we need to specify each
|
||||
content type that we want to remove. To solve this problem Fastify provides the
|
||||
`removeAllContentTypeParsers` API. This can be used to remove all currently
|
||||
existing content type parsers. In the example below we achieve the same as in
|
||||
the example above except that we do not need to specify each content type to
|
||||
delete. Just like `removeContentTypeParser`, this API supports encapsulation.
|
||||
The API is especially useful if you want to register a [catch-all content type
|
||||
parser](#catch-all) that should be executed for every content type and the
|
||||
built-in parsers should be ignored as well.
|
||||
|
||||
```js
|
||||
fastify.removeAllContentTypeParsers()
|
||||
|
||||
fastify.addContentTypeParser('text/xml', function (request, payload, done) {
|
||||
xmlParser(payload, function (err, body) {
|
||||
done(err, body)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**Notice**: The old syntaxes `function(req, done)` and `async function(req)` for
|
||||
the parser are still supported but they are deprecated.
|
||||
|
||||
#### Body Parser
|
||||
You can parse the body of a request in two ways. The first one is shown above:
|
||||
you add a custom content type parser and handle the request stream. In the
|
||||
second one, you should pass a `parseAs` option to the `addContentTypeParser`
|
||||
API, where you declare how you want to get the body. It could be of type
|
||||
`'string'` or `'buffer'`. If you use the `parseAs` option, Fastify will
|
||||
internally handle the stream and perform some checks, such as the [maximum
|
||||
size](./Server.md#factory-body-limit) of the body and the content length. If the
|
||||
limit is exceeded the custom parser will not be invoked.
|
||||
```js
|
||||
fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
|
||||
try {
|
||||
var json = JSON.parse(body)
|
||||
done(null, json)
|
||||
} catch (err) {
|
||||
err.statusCode = 400
|
||||
done(err, undefined)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
See
|
||||
[`example/parser.js`](https://github.com/fastify/fastify/blob/main/examples/parser.js)
|
||||
for an example.
|
||||
|
||||
##### Custom Parser Options
|
||||
+ `parseAs` (string): Either `'string'` or `'buffer'` to designate how the
|
||||
incoming data should be collected. Default: `'buffer'`.
|
||||
+ `bodyLimit` (number): The maximum payload size, in bytes, that the custom
|
||||
parser will accept. Defaults to the global body limit passed to the [`Fastify
|
||||
factory function`](./Server.md#bodylimit).
|
||||
|
||||
#### Catch-All
|
||||
There are some cases where you need to catch all requests regardless of their
|
||||
content type. With Fastify, you can just use the `'*'` content type.
|
||||
```js
|
||||
fastify.addContentTypeParser('*', function (request, payload, done) {
|
||||
var data = ''
|
||||
payload.on('data', chunk => { data += chunk })
|
||||
payload.on('end', () => {
|
||||
done(null, data)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Using this, all requests that do not have a corresponding content type parser
|
||||
will be handled by the specified function.
|
||||
|
||||
This is also useful for piping the request stream. You can define a content
|
||||
parser like:
|
||||
|
||||
```js
|
||||
fastify.addContentTypeParser('*', function (request, payload, done) {
|
||||
done()
|
||||
})
|
||||
```
|
||||
|
||||
and then access the core HTTP request directly for piping it where you want:
|
||||
|
||||
```js
|
||||
app.post('/hello', (request, reply) => {
|
||||
reply.send(request.raw)
|
||||
})
|
||||
```
|
||||
|
||||
Here is a complete example that logs incoming [json
|
||||
line](https://jsonlines.org/) objects:
|
||||
|
||||
```js
|
||||
const split2 = require('split2')
|
||||
const pump = require('pump')
|
||||
|
||||
fastify.addContentTypeParser('*', (request, payload, done) => {
|
||||
done(null, pump(payload, split2(JSON.parse)))
|
||||
})
|
||||
|
||||
fastify.route({
|
||||
method: 'POST',
|
||||
url: '/api/log/jsons',
|
||||
handler: (req, res) => {
|
||||
req.body.on('data', d => console.log(d)) // log every incoming object
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
For piping file uploads you may want to check out [this
|
||||
plugin](https://github.com/fastify/fastify-multipart).
|
||||
|
||||
If you want the content type parser to be executed on all content types and not
|
||||
only on those that don't have a specific one, you should call the
|
||||
`removeAllContentTypeParsers` method first.
|
||||
|
||||
```js
|
||||
// Without this call, the request body with the content type application/json would be processed by the built-in JSON parser
|
||||
fastify.removeAllContentTypeParsers()
|
||||
|
||||
fastify.addContentTypeParser('*', function (request, payload, done) {
|
||||
var data = ''
|
||||
payload.on('data', chunk => { data += chunk })
|
||||
payload.on('end', () => {
|
||||
done(null, data)
|
||||
})
|
||||
})
|
||||
```
|
||||
351
backend/node_modules/fastify/docs/Reference/Decorators.md
generated
vendored
Normal file
351
backend/node_modules/fastify/docs/Reference/Decorators.md
generated
vendored
Normal file
@@ -0,0 +1,351 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Decorators
|
||||
|
||||
The decorators API allows customization of the core Fastify objects, such as the
|
||||
server instance itself and any request and reply objects used during the HTTP
|
||||
request lifecycle. The decorators API can be used to attach any type of property
|
||||
to the core objects, e.g. functions, plain objects, or native types.
|
||||
|
||||
This API is *synchronous*. Attempting to define a decoration asynchronously
|
||||
could result in the Fastify instance booting before the decoration completes its
|
||||
initialization. To avoid this issue, and register an asynchronous decoration,
|
||||
the `register` API, in combination with `fastify-plugin`, must be used instead.
|
||||
To learn more, see the [Plugins](./Plugins.md) documentation.
|
||||
|
||||
Decorating core objects with this API allows the underlying JavaScript engine to
|
||||
optimize the handling of server, request, and reply objects. This is
|
||||
accomplished by defining the shape of all such object instances before they are
|
||||
instantiated and used. As an example, the following is not recommended because
|
||||
it will change the shape of objects during their lifecycle:
|
||||
|
||||
```js
|
||||
// Bad example! Continue reading.
|
||||
|
||||
// Attach a user property to the incoming request before the request
|
||||
// handler is invoked.
|
||||
fastify.addHook('preHandler', function (req, reply, done) {
|
||||
req.user = 'Bob Dylan'
|
||||
done()
|
||||
})
|
||||
|
||||
// Use the attached user property in the request handler.
|
||||
fastify.get('/', function (req, reply) {
|
||||
reply.send(`Hello, ${req.user}`)
|
||||
})
|
||||
```
|
||||
|
||||
Since the above example mutates the request object after it has already been
|
||||
instantiated, the JavaScript engine must deoptimize access to the request
|
||||
object. By using the decoration API this deoptimization is avoided:
|
||||
|
||||
```js
|
||||
// Decorate request with a 'user' property
|
||||
fastify.decorateRequest('user', '')
|
||||
|
||||
// Update our property
|
||||
fastify.addHook('preHandler', (req, reply, done) => {
|
||||
req.user = 'Bob Dylan'
|
||||
done()
|
||||
})
|
||||
// And finally access it
|
||||
fastify.get('/', (req, reply) => {
|
||||
reply.send(`Hello, ${req.user}!`)
|
||||
})
|
||||
```
|
||||
|
||||
Note that it is important to keep the initial shape of a decorated field as
|
||||
close as possible to the value intended to be set dynamically in the future.
|
||||
Initialize a decorator as a `''` if the intended value is a string, and as
|
||||
`null` if it will be an object or a function.
|
||||
|
||||
Remember this example works only with value types as reference types will be
|
||||
shared amongst all requests. See [decorateRequest](#decorate-request).
|
||||
|
||||
See [JavaScript engine fundamentals: Shapes and Inline
|
||||
Caches](https://mathiasbynens.be/notes/shapes-ics) for more information on this
|
||||
topic.
|
||||
|
||||
### Usage
|
||||
<a id="usage"></a>
|
||||
|
||||
#### `decorate(name, value, [dependencies])`
|
||||
<a id="decorate"></a>
|
||||
|
||||
This method is used to customize the Fastify [server](./Server.md)
|
||||
instance.
|
||||
|
||||
For example, to attach a new method to the server instance:
|
||||
|
||||
```js
|
||||
fastify.decorate('utility', function () {
|
||||
// Something very useful
|
||||
})
|
||||
```
|
||||
|
||||
As mentioned above, non-function values can be attached:
|
||||
|
||||
```js
|
||||
fastify.decorate('conf', {
|
||||
db: 'some.db',
|
||||
port: 3000
|
||||
})
|
||||
```
|
||||
|
||||
To access decorated properties, use the name provided to the decoration API:
|
||||
|
||||
```js
|
||||
fastify.utility()
|
||||
|
||||
console.log(fastify.conf.db)
|
||||
```
|
||||
|
||||
The decorated [Fastify server](./Server.md) is bound to `this` in
|
||||
[route](./Routes.md) handlers:
|
||||
|
||||
```js
|
||||
fastify.decorate('db', new DbConnection())
|
||||
|
||||
fastify.get('/', async function (request, reply) {
|
||||
// using return
|
||||
return { hello: await this.db.query('world') }
|
||||
|
||||
// or
|
||||
// using reply.send()
|
||||
reply.send({ hello: await this.db.query('world') })
|
||||
await reply
|
||||
})
|
||||
```
|
||||
|
||||
The `dependencies` parameter is an optional list of decorators that the
|
||||
decorator being defined relies upon. This list is simply a list of string names
|
||||
of other decorators. In the following example, the "utility" decorator depends
|
||||
upon "greet" and "hi" decorators:
|
||||
|
||||
```js
|
||||
async function greetDecorator (fastify, opts) {
|
||||
fastify.decorate('greet', () => {
|
||||
return 'greet message'
|
||||
})
|
||||
}
|
||||
|
||||
async function hiDecorator (fastify, opts) {
|
||||
fastify.decorate('hi', () => {
|
||||
return 'hi message'
|
||||
})
|
||||
}
|
||||
|
||||
async function utilityDecorator (fastify, opts) {
|
||||
fastify.decorate('utility', () => {
|
||||
return `${fastify.greet()} | ${fastify.hi()}`
|
||||
})
|
||||
}
|
||||
|
||||
fastify.register(fastifyPlugin(greetDecorator, { name: 'greet' }))
|
||||
fastify.register(fastifyPlugin(hiDecorator, { name: 'hi' }))
|
||||
fastify.register(fastifyPlugin(utilityDecorator, { dependencies: ['greet', 'hi'] }))
|
||||
|
||||
fastify.get('/', function (req, reply) {
|
||||
// Response: {"hello":"greet message | hi message"}
|
||||
reply.send({ hello: fastify.utility() })
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, (err, address) => {
|
||||
if (err) throw err
|
||||
})
|
||||
```
|
||||
|
||||
Note: using an arrow function will break the binding of `this` to the
|
||||
`FastifyInstance`.
|
||||
|
||||
If a dependency is not satisfied, the `decorate` method will throw an exception.
|
||||
The dependency check is performed before the server instance is booted. Thus, it
|
||||
cannot occur during runtime.
|
||||
|
||||
#### `decorateReply(name, value, [dependencies])`
|
||||
<a id="decorate-reply"></a>
|
||||
|
||||
As the name suggests, this API is used to add new methods/properties to the core
|
||||
`Reply` object:
|
||||
|
||||
```js
|
||||
fastify.decorateReply('utility', function () {
|
||||
// Something very useful
|
||||
})
|
||||
```
|
||||
|
||||
Note: using an arrow function will break the binding of `this` to the Fastify
|
||||
`Reply` instance.
|
||||
|
||||
Note: using `decorateReply` will emit a warning if used with a reference type:
|
||||
|
||||
```js
|
||||
// Don't do this
|
||||
fastify.decorateReply('foo', { bar: 'fizz'})
|
||||
```
|
||||
In this example, the reference of the object is shared with all the requests:
|
||||
**any mutation will impact all requests, potentially creating security
|
||||
vulnerabilities or memory leaks**. To achieve proper encapsulation across
|
||||
requests configure a new value for each incoming request in the [`'onRequest'`
|
||||
hook](./Hooks.md#onrequest). Example:
|
||||
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
async function myPlugin (app) {
|
||||
app.decorateRequest('foo', null)
|
||||
app.addHook('onRequest', async (req, reply) => {
|
||||
req.foo = { bar: 42 }
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = fp(myPlugin)
|
||||
```
|
||||
|
||||
See [`decorate`](#decorate) for information about the `dependencies` parameter.
|
||||
|
||||
#### `decorateRequest(name, value, [dependencies])`
|
||||
<a id="decorate-request"></a>
|
||||
|
||||
As above with [`decorateReply`](#decorate-reply), this API is used add new
|
||||
methods/properties to the core `Request` object:
|
||||
|
||||
```js
|
||||
fastify.decorateRequest('utility', function () {
|
||||
// something very useful
|
||||
})
|
||||
```
|
||||
|
||||
Note: using an arrow function will break the binding of `this` to the Fastify
|
||||
`Request` instance.
|
||||
|
||||
Note: using `decorateRequest` will emit a warning if used with a reference type:
|
||||
|
||||
```js
|
||||
// Don't do this
|
||||
fastify.decorateRequest('foo', { bar: 'fizz'})
|
||||
```
|
||||
In this example, the reference of the object is shared with all the requests:
|
||||
**any mutation will impact all requests, potentially creating security
|
||||
vulnerabilities or memory leaks**.
|
||||
|
||||
To achieve proper encapsulation across requests configure a new value for each
|
||||
incoming request in the [`'onRequest'` hook](./Hooks.md#onrequest). Example:
|
||||
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
async function myPlugin (app) {
|
||||
app.decorateRequest('foo', null)
|
||||
app.addHook('onRequest', async (req, reply) => {
|
||||
req.foo = { bar: 42 }
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = fp(myPlugin)
|
||||
```
|
||||
|
||||
See [`decorate`](#decorate) for information about the `dependencies` parameter.
|
||||
|
||||
#### `hasDecorator(name)`
|
||||
<a id="has-decorator"></a>
|
||||
|
||||
Used to check for the existence of a server instance decoration:
|
||||
|
||||
```js
|
||||
fastify.hasDecorator('utility')
|
||||
```
|
||||
|
||||
#### hasRequestDecorator
|
||||
<a id="has-request-decorator"></a>
|
||||
|
||||
Used to check for the existence of a Request decoration:
|
||||
|
||||
```js
|
||||
fastify.hasRequestDecorator('utility')
|
||||
```
|
||||
|
||||
#### hasReplyDecorator
|
||||
<a id="has-reply-decorator"></a>
|
||||
|
||||
Used to check for the existence of a Reply decoration:
|
||||
|
||||
```js
|
||||
fastify.hasReplyDecorator('utility')
|
||||
```
|
||||
|
||||
### Decorators and Encapsulation
|
||||
<a id="decorators-encapsulation"></a>
|
||||
|
||||
Defining a decorator (using `decorate`, `decorateRequest`, or `decorateReply`)
|
||||
with the same name more than once in the same **encapsulated** context will
|
||||
throw an exception.
|
||||
|
||||
As an example, the following will throw:
|
||||
|
||||
```js
|
||||
const server = require('fastify')()
|
||||
|
||||
server.decorateReply('view', function (template, args) {
|
||||
// Amazing view rendering engine
|
||||
})
|
||||
|
||||
server.get('/', (req, reply) => {
|
||||
reply.view('/index.html', { hello: 'world' })
|
||||
})
|
||||
|
||||
// Somewhere else in our codebase, we define another
|
||||
// view decorator. This throws.
|
||||
server.decorateReply('view', function (template, args) {
|
||||
// Another rendering engine
|
||||
})
|
||||
|
||||
server.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
|
||||
But this will not:
|
||||
|
||||
```js
|
||||
const server = require('fastify')()
|
||||
|
||||
server.decorateReply('view', function (template, args) {
|
||||
// Amazing view rendering engine.
|
||||
})
|
||||
|
||||
server.register(async function (server, opts) {
|
||||
// We add a view decorator to the current encapsulated
|
||||
// plugin. This will not throw as outside of this encapsulated
|
||||
// plugin view is the old one, while inside it is the new one.
|
||||
server.decorateReply('view', function (template, args) {
|
||||
// Another rendering engine
|
||||
})
|
||||
|
||||
server.get('/', (req, reply) => {
|
||||
reply.view('/index.page', { hello: 'world' })
|
||||
})
|
||||
}, { prefix: '/bar' })
|
||||
|
||||
server.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
### Getters and Setters
|
||||
<a id="getters-setters"></a>
|
||||
|
||||
Decorators accept special "getter/setter" objects. These objects have functions
|
||||
named `getter` and `setter` (though the `setter` function is optional). This
|
||||
allows defining properties via decorators, for example:
|
||||
|
||||
```js
|
||||
fastify.decorate('foo', {
|
||||
getter () {
|
||||
return 'a getter'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Will define the `foo` property on the Fastify instance:
|
||||
|
||||
```js
|
||||
console.log(fastify.foo) // 'a getter'
|
||||
```
|
||||
195
backend/node_modules/fastify/docs/Reference/Encapsulation.md
generated
vendored
Normal file
195
backend/node_modules/fastify/docs/Reference/Encapsulation.md
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Encapsulation
|
||||
<a id="encapsulation"></a>
|
||||
|
||||
A fundamental feature of Fastify is the "encapsulation context." The
|
||||
encapsulation context governs which [decorators](./Decorators.md), registered
|
||||
[hooks](./Hooks.md), and [plugins](./Plugins.md) are available to
|
||||
[routes](./Routes.md). A visual representation of the encapsulation context
|
||||
is shown in the following figure:
|
||||
|
||||

|
||||
|
||||
In the above figure, there are several entities:
|
||||
|
||||
1. The _root context_
|
||||
2. Three _root plugins_
|
||||
3. Two _child contexts_ where each _child context_ has
|
||||
* Two _child plugins_
|
||||
* One _grandchild context_ where each _grandchild context_ has
|
||||
- Three _child plugins_
|
||||
|
||||
Every _child context_ and _grandchild context_ has access to the _root plugins_.
|
||||
Within each _child context_, the _grandchild contexts_ have access to the
|
||||
_child plugins_ registered within the containing _child context_, but the
|
||||
containing _child context_ **does not** have access to the _child plugins_
|
||||
registered within its _grandchild context_.
|
||||
|
||||
Given that everything in Fastify is a [plugin](./Plugins.md), except for the
|
||||
_root context_, every "context" and "plugin" in this example is a plugin
|
||||
that can consist of decorators, hooks, plugins, and routes. Thus, to put
|
||||
this example into concrete terms, consider a basic scenario of a REST API
|
||||
server that has three routes: the first route (`/one`) requires authentication,
|
||||
the second route (`/two`) does not, and the third route (`/three`) has
|
||||
access to the same context as the second route. Using
|
||||
[@fastify/bearer-auth][bearer] to provide the authentication, the code for this
|
||||
example is as follows:
|
||||
|
||||
```js
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')()
|
||||
|
||||
fastify.decorateRequest('answer', 42)
|
||||
|
||||
fastify.register(async function authenticatedContext (childServer) {
|
||||
childServer.register(require('@fastify/bearer-auth'), { keys: ['abc123'] })
|
||||
|
||||
childServer.route({
|
||||
path: '/one',
|
||||
method: 'GET',
|
||||
handler (request, response) {
|
||||
response.send({
|
||||
answer: request.answer,
|
||||
// request.foo will be undefined as it's only defined in publicContext
|
||||
foo: request.foo,
|
||||
// request.bar will be undefined as it's only defined in grandchildContext
|
||||
bar: request.bar
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
fastify.register(async function publicContext (childServer) {
|
||||
childServer.decorateRequest('foo', 'foo')
|
||||
|
||||
childServer.route({
|
||||
path: '/two',
|
||||
method: 'GET',
|
||||
handler (request, response) {
|
||||
response.send({
|
||||
answer: request.answer,
|
||||
foo: request.foo,
|
||||
// request.bar will be undefined as it's only defined in grandchildContext
|
||||
bar: request.bar
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
childServer.register(async function grandchildContext (grandchildServer) {
|
||||
grandchildServer.decorateRequest('bar', 'bar')
|
||||
|
||||
grandchildServer.route({
|
||||
path: '/three',
|
||||
method: 'GET',
|
||||
handler (request, response) {
|
||||
response.send({
|
||||
answer: request.answer,
|
||||
foo: request.foo,
|
||||
bar: request.bar
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
fastify.listen({ port: 8000 })
|
||||
```
|
||||
|
||||
The above server example shows all of the encapsulation concepts outlined in the
|
||||
original diagram:
|
||||
|
||||
1. Each _child context_ (`authenticatedContext`, `publicContext`, and
|
||||
`grandchildContext`) has access to the `answer` request decorator defined in
|
||||
the _root context_.
|
||||
2. Only the `authenticatedContext` has access to the `@fastify/bearer-auth`
|
||||
plugin.
|
||||
3. Both the `publicContext` and `grandchildContext` have access to the `foo`
|
||||
request decorator.
|
||||
4. Only the `grandchildContext` has access to the `bar` request decorator.
|
||||
|
||||
To see this, start the server and issue requests:
|
||||
|
||||
```sh
|
||||
# curl -H 'authorization: Bearer abc123' http://127.0.0.1:8000/one
|
||||
{"answer":42}
|
||||
# curl http://127.0.0.1:8000/two
|
||||
{"answer":42,"foo":"foo"}
|
||||
# curl http://127.0.0.1:8000/three
|
||||
{"answer":42,"foo":"foo","bar":"bar"}
|
||||
```
|
||||
|
||||
[bearer]: https://github.com/fastify/fastify-bearer-auth
|
||||
|
||||
## Sharing Between Contexts
|
||||
<a id="shared-context"></a>
|
||||
|
||||
Notice that each context in the prior example inherits _only_ from the parent
|
||||
contexts. Parent contexts cannot access any entities within their descendent
|
||||
contexts. This default is occasionally not desired. In such cases, the
|
||||
encapsulation context can be broken through the usage of
|
||||
[fastify-plugin][fastify-plugin] such that anything registered in a descendent
|
||||
context is available to the containing parent context.
|
||||
|
||||
Assuming the `publicContext` needs access to the `bar` decorator defined
|
||||
within the `grandchildContext` in the previous example, the code can be
|
||||
rewritten as:
|
||||
|
||||
```js
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')()
|
||||
const fastifyPlugin = require('fastify-plugin')
|
||||
|
||||
fastify.decorateRequest('answer', 42)
|
||||
|
||||
// `authenticatedContext` omitted for clarity
|
||||
|
||||
fastify.register(async function publicContext (childServer) {
|
||||
childServer.decorateRequest('foo', 'foo')
|
||||
|
||||
childServer.route({
|
||||
path: '/two',
|
||||
method: 'GET',
|
||||
handler (request, response) {
|
||||
response.send({
|
||||
answer: request.answer,
|
||||
foo: request.foo,
|
||||
bar: request.bar
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
childServer.register(fastifyPlugin(grandchildContext))
|
||||
|
||||
async function grandchildContext (grandchildServer) {
|
||||
grandchildServer.decorateRequest('bar', 'bar')
|
||||
|
||||
grandchildServer.route({
|
||||
path: '/three',
|
||||
method: 'GET',
|
||||
handler (request, response) {
|
||||
response.send({
|
||||
answer: request.answer,
|
||||
foo: request.foo,
|
||||
bar: request.bar
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
fastify.listen({ port: 8000 })
|
||||
```
|
||||
|
||||
Restarting the server and re-issuing the requests for `/two` and `/three`:
|
||||
|
||||
```sh
|
||||
# curl http://127.0.0.1:8000/two
|
||||
{"answer":42,"foo":"foo","bar":"bar"}
|
||||
# curl http://127.0.0.1:8000/three
|
||||
{"answer":42,"foo":"foo","bar":"bar"}
|
||||
```
|
||||
|
||||
[fastify-plugin]: https://github.com/fastify/fastify-plugin
|
||||
365
backend/node_modules/fastify/docs/Reference/Errors.md
generated
vendored
Normal file
365
backend/node_modules/fastify/docs/Reference/Errors.md
generated
vendored
Normal file
@@ -0,0 +1,365 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Errors
|
||||
<a id="errors"></a>
|
||||
|
||||
**Table of contents**
|
||||
- [Errors](#errors)
|
||||
- [Error Handling In Node.js](#error-handling-in-node.js)
|
||||
- [Uncaught Errors](#uncaught-errors)
|
||||
- [Catching Errors In Promises](#catching-errors-in-promises)
|
||||
- [Errors In Fastify](#errors-in-fastify)
|
||||
- [Errors In Input Data](#errors-in-input-data)
|
||||
- [Catching Uncaught Errors In Fastify](#catching-uncaught-errors-in-fastify)
|
||||
- [Errors In Fastify Lifecycle Hooks And A Custom Error Handler](#errors-in-fastify-lifecycle-hooks-and-a-custom-error-handler)
|
||||
- [Fastify Error Codes](#fastify-error-codes)
|
||||
- [FST_ERR_NOT_FOUND](#fst_err_not_found)
|
||||
- [FST_ERR_OPTIONS_NOT_OBJ](#fst_err_options_not_obj)
|
||||
- [FST_ERR_QSP_NOT_FN](#fst_err_qsp_not_fn)
|
||||
- [FST_ERR_SCHEMA_CONTROLLER_BUCKET_OPT_NOT_FN](#fst_err_schema_controller_bucket_opt_not_fn)
|
||||
- [FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN](#fst_err_schema_error_formatter_not_fn)
|
||||
- [FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ](#fst_err_ajv_custom_options_opt_not_obj)
|
||||
- [FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR](#fst_err_ajv_custom_options_opt_not_arr)
|
||||
- [FST_ERR_VERSION_CONSTRAINT_NOT_STR](#fst_err_version_constraint_not_str)
|
||||
- [FST_ERR_CTP_ALREADY_PRESENT](#fst_err_ctp_already_present)
|
||||
- [FST_ERR_CTP_INVALID_TYPE](#fst_err_ctp_invalid_type)
|
||||
- [FST_ERR_CTP_EMPTY_TYPE](#fst_err_ctp_empty_type)
|
||||
- [FST_ERR_CTP_INVALID_HANDLER](#fst_err_ctp_invalid_handler)
|
||||
- [FST_ERR_CTP_INVALID_PARSE_TYPE](#fst_err_ctp_invalid_parse_type)
|
||||
- [FST_ERR_CTP_BODY_TOO_LARGE](#fst_err_ctp_body_too_large)
|
||||
- [FST_ERR_CTP_INVALID_MEDIA_TYPE](#fst_err_ctp_invalid_media_type)
|
||||
- [FST_ERR_CTP_INVALID_CONTENT_LENGTH](#fst_err_ctp_invalid_content_length)
|
||||
- [FST_ERR_CTP_EMPTY_JSON_BODY](#fst_err_ctp_empty_json_body)
|
||||
- [FST_ERR_CTP_INSTANCE_ALREADY_STARTED](#fst_err_ctp_instance_already_started)
|
||||
- [FST_ERR_INSTANCE_ALREADY_LISTENING](#fst_err_instance_already_listening)
|
||||
- [FST_ERR_DEC_ALREADY_PRESENT](#fst_err_dec_already_present)
|
||||
- [FST_ERR_DEC_DEPENDENCY_INVALID_TYPE](#fst_err_dec_dependency_invalid_type)
|
||||
- [FST_ERR_DEC_MISSING_DEPENDENCY](#fst_err_dec_missing_dependency)
|
||||
- [FST_ERR_DEC_AFTER_START](#fst_err_dec_after_start)
|
||||
- [FST_ERR_HOOK_INVALID_TYPE](#fst_err_hook_invalid_type)
|
||||
- [FST_ERR_HOOK_INVALID_HANDLER](#fst_err_hook_invalid_handler)
|
||||
- [FST_ERR_HOOK_INVALID_ASYNC_HANDLER](#fst_err_hook_invalid_async_handler)
|
||||
- [FST_ERR_HOOK_NOT_SUPPORTED](#fst_err_hook_not_supported)
|
||||
- [FST_ERR_MISSING_MIDDLEWARE](#fst_err_missing_middleware)
|
||||
- [FST_ERR_HOOK_TIMEOUT](#fst_err_hook_timeout)
|
||||
- [FST_ERR_LOG_INVALID_DESTINATION](#fst_err_log_invalid_destination)
|
||||
- [FST_ERR_LOG_INVALID_LOGGER](#fst_err_log_invalid_logger)
|
||||
- [FST_ERR_REP_INVALID_PAYLOAD_TYPE](#fst_err_rep_invalid_payload_type)
|
||||
- [FST_ERR_REP_RESPONSE_BODY_CONSUMED](#fst_err_rep_response_body_consumed)
|
||||
- [FST_ERR_REP_ALREADY_SENT](#fst_err_rep_already_sent)
|
||||
- [FST_ERR_REP_SENT_VALUE](#fst_err_rep_sent_value)
|
||||
- [FST_ERR_SEND_INSIDE_ONERR](#fst_err_send_inside_onerr)
|
||||
- [FST_ERR_SEND_UNDEFINED_ERR](#fst_err_send_undefined_err)
|
||||
- [FST_ERR_BAD_STATUS_CODE](#fst_err_bad_status_code)
|
||||
- [FST_ERR_BAD_TRAILER_NAME](#fst_err_bad_trailer_name)
|
||||
- [FST_ERR_BAD_TRAILER_VALUE](#fst_err_bad_trailer_value)
|
||||
- [FST_ERR_FAILED_ERROR_SERIALIZATION](#fst_err_failed_error_serialization)
|
||||
- [FST_ERR_MISSING_SERIALIZATION_FN](#fst_err_missing_serialization_fn)
|
||||
- [FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN](#fst_err_missing_contenttype_serialization_fn)
|
||||
- [FST_ERR_REQ_INVALID_VALIDATION_INVOCATION](#fst_err_req_invalid_validation_invocation)
|
||||
- [FST_ERR_SCH_MISSING_ID](#fst_err_sch_missing_id)
|
||||
- [FST_ERR_SCH_ALREADY_PRESENT](#fst_err_sch_already_present)
|
||||
- [FST_ERR_SCH_CONTENT_MISSING_SCHEMA](#fst_err_sch_content_missing_schema)
|
||||
- [FST_ERR_SCH_DUPLICATE](#fst_err_sch_duplicate)
|
||||
- [FST_ERR_SCH_VALIDATION_BUILD](#fst_err_sch_validation_build)
|
||||
- [FST_ERR_SCH_SERIALIZATION_BUILD](#fst_err_sch_serialization_build)
|
||||
- [FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX](#fst_err_sch_response_schema_not_nested_2xx)
|
||||
- [FST_ERR_HTTP2_INVALID_VERSION](#fst_err_http2_invalid_version)
|
||||
- [FST_ERR_INIT_OPTS_INVALID](#fst_err_init_opts_invalid)
|
||||
- [FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE](#fst_err_force_close_connections_idle_not_available)
|
||||
- [FST_ERR_DUPLICATED_ROUTE](#fst_err_duplicated_route)
|
||||
- [FST_ERR_BAD_URL](#fst_err_bad_url)
|
||||
- [FST_ERR_ASYNC_CONSTRAINT](#fst_err_async_constraint)
|
||||
- [FST_ERR_DEFAULT_ROUTE_INVALID_TYPE](#fst_err_default_route_invalid_type)
|
||||
- [FST_ERR_INVALID_URL](#fst_err_invalid_url)
|
||||
- [FST_ERR_ROUTE_OPTIONS_NOT_OBJ](#fst_err_route_options_not_obj)
|
||||
- [FST_ERR_ROUTE_DUPLICATED_HANDLER](#fst_err_route_duplicated_handler)
|
||||
- [FST_ERR_ROUTE_HANDLER_NOT_FN](#fst_err_route_handler_not_fn)
|
||||
- [FST_ERR_ROUTE_MISSING_HANDLER](#fst_err_route_missing_handler)
|
||||
- [FST_ERR_ROUTE_METHOD_INVALID](#fst_err_route_method_invalid)
|
||||
- [FST_ERR_ROUTE_METHOD_NOT_SUPPORTED](#fst_err_route_method_not_supported)
|
||||
- [FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED](#fst_err_route_body_validation_schema_not_supported)
|
||||
- [FST_ERR_ROUTE_BODY_LIMIT_OPTION_NOT_INT](#fst_err_route_body_limit_option_not_int)
|
||||
- [FST_ERR_ROUTE_REWRITE_NOT_STR](#fst_err_route_rewrite_not_str)
|
||||
- [FST_ERR_REOPENED_CLOSE_SERVER](#fst_err_reopened_close_server)
|
||||
- [FST_ERR_REOPENED_SERVER](#fst_err_reopened_server)
|
||||
- [FST_ERR_PLUGIN_VERSION_MISMATCH](#fst_err_plugin_version_mismatch)
|
||||
- [FST_ERR_PLUGIN_CALLBACK_NOT_FN](#fst_err_plugin_callback_not_fn)
|
||||
- [FST_ERR_PLUGIN_NOT_VALID](#fst_err_plugin_not_valid)
|
||||
- [FST_ERR_ROOT_PLG_BOOTED](#fst_err_root_plg_booted)
|
||||
- [FST_ERR_PARENT_PLUGIN_BOOTED](#fst_err_parent_plugin_booted)
|
||||
- [FST_ERR_PLUGIN_TIMEOUT](#fst_err_plugin_timeout)
|
||||
- [FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE](#fst_err_plugin_not_present_in_instance)
|
||||
- [FST_ERR_VALIDATION](#fst_err_validation)
|
||||
- [FST_ERR_LISTEN_OPTIONS_INVALID](#fst_err_listen_options_invalid)
|
||||
- [FST_ERR_ERROR_HANDLER_NOT_FN](#fst_err_error_handler_not_fn)
|
||||
|
||||
### Error Handling In Node.js
|
||||
<a id="error-handling"></a>
|
||||
|
||||
#### Uncaught Errors
|
||||
In Node.js, uncaught errors are likely to cause memory leaks, file descriptor
|
||||
leaks, and other major production issues.
|
||||
[Domains](https://nodejs.org/en/docs/guides/domain-postmortem/) were a failed
|
||||
attempt to fix this.
|
||||
|
||||
Given that it is not possible to process all uncaught errors sensibly, the best
|
||||
way to deal with them is to
|
||||
[crash](https://nodejs.org/api/process.html#process_warning_using_uncaughtexception_correctly).
|
||||
|
||||
#### Catching Errors In Promises
|
||||
If you are using promises, you should attach a `.catch()` handler synchronously.
|
||||
|
||||
### Errors In Fastify
|
||||
Fastify follows an all-or-nothing approach and aims to be lean and optimal as
|
||||
much as possible. The developer is responsible for making sure that the errors
|
||||
are handled properly.
|
||||
|
||||
#### Errors In Input Data
|
||||
Most errors are a result of unexpected input data, so we recommend [validating
|
||||
your input data against a JSON schema](./Validation-and-Serialization.md).
|
||||
|
||||
#### Catching Uncaught Errors In Fastify
|
||||
Fastify tries to catch as many uncaught errors as it can without hindering
|
||||
performance. This includes:
|
||||
|
||||
1. synchronous routes, e.g. `app.get('/', () => { throw new Error('kaboom') })`
|
||||
2. `async` routes, e.g. `app.get('/', async () => { throw new Error('kaboom')
|
||||
})`
|
||||
|
||||
The error in both cases will be caught safely and routed to Fastify's default
|
||||
error handler for a generic `500 Internal Server Error` response.
|
||||
|
||||
To customize this behavior you should use
|
||||
[`setErrorHandler`](./Server.md#seterrorhandler).
|
||||
|
||||
### Errors In Fastify Lifecycle Hooks And A Custom Error Handler
|
||||
|
||||
From the [Hooks documentation](./Hooks.md#manage-errors-from-a-hook):
|
||||
> If you get an error during the execution of your hook, just pass it to
|
||||
> `done()` and Fastify will automatically close the request and send the
|
||||
> appropriate error code to the user.
|
||||
|
||||
When a custom error handler has been defined through
|
||||
[`setErrorHandler`](./Server.md#seterrorhandler), the custom error handler will
|
||||
receive the error passed to the `done()` callback (or through other supported
|
||||
automatic error handling mechanisms). If `setErrorHandler` has been used
|
||||
multiple times to define multiple handlers, the error will be routed to the most
|
||||
precedent handler defined within the error [encapsulation
|
||||
context](./Encapsulation.md). Error handlers are fully encapsulated, so a
|
||||
`setErrorHandler` call within a plugin will limit the error handler to that
|
||||
plugin's context.
|
||||
|
||||
The root error handler is Fastify's generic error handler. This error handler
|
||||
will use the headers and status code in the `Error` object, if they exist. The
|
||||
headers and status code will not be automatically set if a custom error handler
|
||||
is provided.
|
||||
|
||||
Some things to consider in your custom error handler:
|
||||
|
||||
- you can `reply.send(data)`, which will behave as it would in [regular route
|
||||
handlers](./Reply.md#senddata)
|
||||
- objects are serialized, triggering the `preSerialization` lifecycle hook if
|
||||
you have one defined
|
||||
- strings, buffers, and streams are sent to the client, with appropriate
|
||||
headers (no serialization)
|
||||
|
||||
- You can throw a new error in your custom error handler - errors (new error or
|
||||
the received error parameter re-thrown) - will call the parent `errorHandler`.
|
||||
- `onError` hook will be triggered once only for the first error being thrown.
|
||||
- an error will not be triggered twice from a lifecycle hook - Fastify
|
||||
internally monitors the error invocation to avoid infinite loops for errors
|
||||
thrown in the reply phases of the lifecycle. (those after the route handler)
|
||||
|
||||
When utilizing Fastify's custom error handling through [`setErrorHandler`](./Server.md#seterrorhandler),
|
||||
you should be aware of how errors are propagated between custom and default
|
||||
error handlers.
|
||||
|
||||
If a plugin's error handler re-throws an error, and the error is not an
|
||||
instance of [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)
|
||||
(as seen in the `/bad` route in the following example), it will not propagate
|
||||
to the parent context error handler. Instead, it will be caught by the default
|
||||
error handler.
|
||||
|
||||
To ensure consistent error handling, it is recommended to throw instances of
|
||||
`Error`. For instance, in the following example, replacing `throw 'foo'` with
|
||||
`throw new Error('foo')` in the `/bad` route ensures that errors propagate through
|
||||
the custom error handling chain as intended. This practice helps avoid potential
|
||||
pitfalls when working with custom error handling in Fastify.
|
||||
|
||||
For example:
|
||||
```js
|
||||
const Fastify = require('fastify')
|
||||
|
||||
// Instantiate the framework
|
||||
const fastify = Fastify({
|
||||
logger: true
|
||||
})
|
||||
|
||||
// Register parent error handler
|
||||
fastify.setErrorHandler((error, request, reply) => {
|
||||
reply.status(500).send({ ok: false })
|
||||
})
|
||||
|
||||
fastify.register((app, options, next) => {
|
||||
// Register child error handler
|
||||
fastify.setErrorHandler((error, request, reply) => {
|
||||
throw error
|
||||
})
|
||||
|
||||
fastify.get('/bad', async () => {
|
||||
// Throws a non-Error type, 'bar'
|
||||
throw 'foo'
|
||||
})
|
||||
|
||||
fastify.get('/good', async () => {
|
||||
// Throws an Error instance, 'bar'
|
||||
throw new Error('bar')
|
||||
})
|
||||
|
||||
next()
|
||||
})
|
||||
|
||||
// Run the server
|
||||
fastify.listen({ port: 3000 }, function (err, address) {
|
||||
if (err) {
|
||||
fastify.log.error(err)
|
||||
process.exit(1)
|
||||
}
|
||||
// Server is listening at ${address}
|
||||
})
|
||||
```
|
||||
|
||||
### Fastify Error Codes
|
||||
<a id="fastify-error-codes"></a>
|
||||
|
||||
You can access `errorCodes` for mapping:
|
||||
```js
|
||||
// ESM
|
||||
import { errorCodes } from 'fastify'
|
||||
|
||||
// CommonJs
|
||||
const errorCodes = require('fastify').errorCodes
|
||||
```
|
||||
|
||||
For example:
|
||||
```js
|
||||
const Fastify = require('fastify')
|
||||
|
||||
// Instantiate the framework
|
||||
const fastify = Fastify({
|
||||
logger: true
|
||||
})
|
||||
|
||||
// Declare a route
|
||||
fastify.get('/', function (request, reply) {
|
||||
reply.code('bad status code').send({ hello: 'world' })
|
||||
})
|
||||
|
||||
fastify.setErrorHandler(function (error, request, reply) {
|
||||
if (error instanceof Fastify.errorCodes.FST_ERR_BAD_STATUS_CODE) {
|
||||
// Log error
|
||||
this.log.error(error)
|
||||
// Send error response
|
||||
reply.status(500).send({ ok: false })
|
||||
} else {
|
||||
// fastify will use parent error handler to handle this
|
||||
reply.send(error)
|
||||
}
|
||||
})
|
||||
|
||||
// Run the server!
|
||||
fastify.listen({ port: 3000 }, function (err, address) {
|
||||
if (err) {
|
||||
fastify.log.error(err)
|
||||
process.exit(1)
|
||||
}
|
||||
// Server is now listening on ${address}
|
||||
})
|
||||
```
|
||||
|
||||
Below is a table with all the error codes that Fastify uses.
|
||||
|
||||
| Code | Description | How to solve | Discussion |
|
||||
|------|-------------|--------------|------------|
|
||||
| <a id="fst_err_not_found">FST_ERR_NOT_FOUND</a> | 404 Not Found | - | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_options_not_obj">FST_ERR_OPTIONS_NOT_OBJ</a> | Fastify options wrongly specified. | Fastify options should be an object. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_qsp_not_fn">FST_ERR_QSP_NOT_FN</a> | QueryStringParser wrongly specified. | QueryStringParser option should be a function. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_schema_controller_bucket_opt_not_fn">FST_ERR_SCHEMA_CONTROLLER_BUCKET_OPT_NOT_FN</a> | SchemaController.bucket wrongly specified. | SchemaController.bucket option should be a function. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_schema_error_formatter_not_fn">FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN</a> | SchemaErrorFormatter option wrongly specified. | SchemaErrorFormatter option should be a non async function. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_ajv_custom_options_opt_not_obj">FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ</a> | ajv.customOptions wrongly specified. | ajv.customOptions option should be an object. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_ajv_custom_options_opt_not_arr">FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR</a> | ajv.plugins option wrongly specified. | ajv.plugins option should be an array. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_version_constraint_not_str">FST_ERR_VERSION_CONSTRAINT_NOT_STR</a> | Version constraint wrongly specified. | Version constraint should be a string. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_ctp_already_present">FST_ERR_CTP_ALREADY_PRESENT</a> | The parser for this content type was already registered. | Use a different content type or delete the already registered parser. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_ctp_invalid_type">FST_ERR_CTP_INVALID_TYPE</a> | `Content-Type` wrongly specified | The `Content-Type` should be a string. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_ctp_empty_type">FST_ERR_CTP_EMPTY_TYPE</a> | `Content-Type` is an empty string. | `Content-Type` cannot be an empty string. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_ctp_invalid_handler">FST_ERR_CTP_INVALID_HANDLER</a> | Invalid handler for the content type. | Use a different handler. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_ctp_invalid_parse_type">FST_ERR_CTP_INVALID_PARSE_TYPE</a> | The provided parse type is not supported. | Accepted values are <code>string</code> or <code>buffer</code>. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_ctp_body_too_large">FST_ERR_CTP_BODY_TOO_LARGE</a> | The request body is larger than the provided limit. | Increase the limit in the Fastify server instance setting: [bodyLimit](./Server.md#bodylimit) | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_ctp_invalid_media_type">FST_ERR_CTP_INVALID_MEDIA_TYPE</a> | The received media type is not supported (i.e. there is no suitable `Content-Type` parser for it). | Use a different content type. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_ctp_invalid_content_length">FST_ERR_CTP_INVALID_CONTENT_LENGTH</a> | Request body size did not match <code>Content-Length</code>. | Check the request body size and the <code>Content-Length</code> header. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_ctp_empty_json_body">FST_ERR_CTP_EMPTY_JSON_BODY</a> | Body cannot be empty when content-type is set to <code>application/json</code>. | Check the request body. | [#1253](https://github.com/fastify/fastify/pull/1253) |
|
||||
| <a id="fst_err_ctp_instance_already_started">FST_ERR_CTP_INSTANCE_ALREADY_STARTED</a> | Fastify is already started. | - | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_instance_already_listening">FST_ERR_INSTANCE_ALREADY_LISTENING</a> | Fastify instance is already listening. | - | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_dec_already_present">FST_ERR_DEC_ALREADY_PRESENT</a> | A decorator with the same name is already registered. | Use a different decorator name. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_dec_dependency_invalid_type">FST_ERR_DEC_DEPENDENCY_INVALID_TYPE</a> | The dependencies of decorator must be of type `Array`. | Use an array for the dependencies. | [#3090](https://github.com/fastify/fastify/pull/3090) |
|
||||
| <a id="fst_err_dec_missing_dependency">FST_ERR_DEC_MISSING_DEPENDENCY</a> | The decorator cannot be registered due to a missing dependency. | Register the missing dependency. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_dec_after_start">FST_ERR_DEC_AFTER_START</a> | The decorator cannot be added after start. | Add the decorator before starting the server. | [#2128](https://github.com/fastify/fastify/pull/2128) |
|
||||
| <a id="fst_err_hook_invalid_type">FST_ERR_HOOK_INVALID_TYPE</a> | The hook name must be a string. | Use a string for the hook name. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_hook_invalid_handler">FST_ERR_HOOK_INVALID_HANDLER</a> | The hook callback must be a function. | Use a function for the hook callback. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_hook_invalid_async_handler">FST_ERR_HOOK_INVALID_ASYNC_HANDLER</a> | Async function has too many arguments. Async hooks should not use the `done` argument. | Remove the `done` argument from the async hook. | [#4367](https://github.com/fastify/fastify/pull/4367) |
|
||||
| <a id="fst_err_hook_not_supported">FST_ERR_HOOK_NOT_SUPPORTED</a> | The hook is not supported. | Use a supported hook. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_missing_middleware">FST_ERR_MISSING_MIDDLEWARE</a> | You must register a plugin for handling middlewares, visit [`Middleware`](./Middleware.md) for more info. | Register a plugin for handling middlewares. | [#2014](https://github.com/fastify/fastify/pull/2014) |
|
||||
| <a id="fst_err_hook_timeout">FST_ERR_HOOK_TIMEOUT</a> | A callback for a hook timed out. | Increase the timeout for the hook. | [#3106](https://github.com/fastify/fastify/pull/3106) |
|
||||
| <a id="fst_err_log_invalid_destination">FST_ERR_LOG_INVALID_DESTINATION</a> | The logger does not accept the specified destination. | Use a `'stream'` or a `'file'` as the destination. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_log_invalid_logger">FST_ERR_LOG_INVALID_LOGGER</a> | The logger should have all these methods: `'info'`, `'error'`, `'debug'`, `'fatal'`, `'warn'`, `'trace'`, `'child'`. | Use a logger with all the required methods. | [#4520](https://github.com/fastify/fastify/pull/4520) |
|
||||
| <a id="fst_err_rep_invalid_payload_type">FST_ERR_REP_INVALID_PAYLOAD_TYPE</a> | Reply payload can be either a `string` or a `Buffer`. | Use a `string` or a `Buffer` for the payload. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_rep_response_body_consumed">FST_ERR_REP_RESPONSE_BODY_CONSUMED</a> | Using `Response` as reply payload, but the body is being consumed. | Make sure you don't consume the `Response.body` | [#5286](https://github.com/fastify/fastify/pull/5286) |
|
||||
| <a id="fst_err_rep_already_sent">FST_ERR_REP_ALREADY_SENT</a> | A response was already sent. | - | [#1336](https://github.com/fastify/fastify/pull/1336) |
|
||||
| <a id="fst_err_rep_sent_value">FST_ERR_REP_SENT_VALUE</a> | The only possible value for `reply.sent` is `true`. | - | [#1336](https://github.com/fastify/fastify/pull/1336) |
|
||||
| <a id="fst_err_send_inside_onerr">FST_ERR_SEND_INSIDE_ONERR</a> | You cannot use `send` inside the `onError` hook. | - | [#1348](https://github.com/fastify/fastify/pull/1348) |
|
||||
| <a id="fst_err_send_undefined_err">FST_ERR_SEND_UNDEFINED_ERR</a> | Undefined error has occurred. | - | [#2074](https://github.com/fastify/fastify/pull/2074) |
|
||||
| <a id="fst_err_bad_status_code">FST_ERR_BAD_STATUS_CODE</a> | The status code is not valid. | Use a valid status code. | [#2082](https://github.com/fastify/fastify/pull/2082) |
|
||||
| <a id="fst_err_bad_trailer_name">FST_ERR_BAD_TRAILER_NAME</a> | Called `reply.trailer` with an invalid header name. | Use a valid header name. | [#3794](https://github.com/fastify/fastify/pull/3794) |
|
||||
| <a id="fst_err_bad_trailer_value">FST_ERR_BAD_TRAILER_VALUE</a> | Called `reply.trailer` with an invalid type. Expected a function. | Use a function. | [#3794](https://github.com/fastify/fastify/pull/3794) |
|
||||
| <a id="fst_err_failed_error_serialization">FST_ERR_FAILED_ERROR_SERIALIZATION</a> | Failed to serialize an error. | - | [#4601](https://github.com/fastify/fastify/pull/4601) |
|
||||
| <a id="fst_err_missing_serialization_fn">FST_ERR_MISSING_SERIALIZATION_FN</a> | Missing serialization function. | Add a serialization function. | [#3970](https://github.com/fastify/fastify/pull/3970) |
|
||||
| <a id="fst_err_missing_contenttype_serialization_fn">FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN</a> | Missing `Content-Type` serialization function. | Add a serialization function. | [#4264](https://github.com/fastify/fastify/pull/4264) |
|
||||
| <a id="fst_err_req_invalid_validation_invocation">FST_ERR_REQ_INVALID_VALIDATION_INVOCATION</a> | Invalid validation invocation. Missing validation function for HTTP part nor schema provided. | Add a validation function. | [#3970](https://github.com/fastify/fastify/pull/3970) |
|
||||
| <a id="fst_err_sch_missing_id">FST_ERR_SCH_MISSING_ID</a> | The schema provided does not have `$id` property. | Add a `$id` property. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_sch_already_present">FST_ERR_SCH_ALREADY_PRESENT</a> | A schema with the same `$id` already exists. | Use a different `$id`. | [#1168](https://github.com/fastify/fastify/pull/1168) |
|
||||
| <a id="fst_err_sch_content_missing_schema">FST_ERR_SCH_CONTENT_MISSING_SCHEMA</a> | A schema is missing for the corresponding content type. | Add a schema. | [#4264](https://github.com/fastify/fastify/pull/4264) |
|
||||
| <a id="fst_err_sch_duplicate">FST_ERR_SCH_DUPLICATE</a> | Schema with the same attribute already present! | Use a different attribute. | [#1954](https://github.com/fastify/fastify/pull/1954) |
|
||||
| <a id="fst_err_sch_validation_build">FST_ERR_SCH_VALIDATION_BUILD</a> | The JSON schema provided for validation to a route is not valid. | Fix the JSON schema. | [#2023](https://github.com/fastify/fastify/pull/2023) |
|
||||
| <a id="fst_err_sch_serialization_build">FST_ERR_SCH_SERIALIZATION_BUILD</a> | The JSON schema provided for serialization of a route response is not valid. | Fix the JSON schema. | [#2023](https://github.com/fastify/fastify/pull/2023) |
|
||||
| <a id="fst_err_sch_response_schema_not_nested_2xx">FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX</a> | Response schemas should be nested under a valid status code (2XX). | Use a valid status code. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_http2_invalid_version">FST_ERR_HTTP2_INVALID_VERSION</a> | HTTP2 is available only from node >= 8.8.1. | Use a higher version of node. | [#1346](https://github.com/fastify/fastify/pull/1346) |
|
||||
| <a id="fst_err_init_opts_invalid">FST_ERR_INIT_OPTS_INVALID</a> | Invalid initialization options. | Use valid initialization options. | [#1471](https://github.com/fastify/fastify/pull/1471) |
|
||||
| <a id="fst_err_force_close_connections_idle_not_available">FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE</a> | Cannot set forceCloseConnections to `idle` as your HTTP server does not support `closeIdleConnections` method. | Use a different value for `forceCloseConnections`. | [#3925](https://github.com/fastify/fastify/pull/3925) |
|
||||
| <a id="fst_err_duplicated_route">FST_ERR_DUPLICATED_ROUTE</a> | The HTTP method already has a registered controller for that URL. | Use a different URL or register the controller for another HTTP method. | [#2954](https://github.com/fastify/fastify/pull/2954) |
|
||||
| <a id="fst_err_bad_url">FST_ERR_BAD_URL</a> | The router received an invalid URL. | Use a valid URL. | [#2106](https://github.com/fastify/fastify/pull/2106) |
|
||||
| <a id="fst_err_async_constraint">FST_ERR_ASYNC_CONSTRAINT</a> | The router received an error when using asynchronous constraints. | - | [#4323](https://github.com/fastify/fastify/pull/4323) |
|
||||
| <a id="fst_err_default_route_invalid_type">FST_ERR_DEFAULT_ROUTE_INVALID_TYPE</a> | The `defaultRoute` type should be a function. | Use a function for the `defaultRoute`. | [#2733](https://github.com/fastify/fastify/pull/2733) |
|
||||
| <a id="fst_err_invalid_url">FST_ERR_INVALID_URL</a> | URL must be a string. | Use a string for the URL. | [#3653](https://github.com/fastify/fastify/pull/3653) |
|
||||
| <a id="fst_err_route_options_not_obj">FST_ERR_ROUTE_OPTIONS_NOT_OBJ</a> | Options for the route must be an object. | Use an object for the route options. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_route_duplicated_handler">FST_ERR_ROUTE_DUPLICATED_HANDLER</a> | Duplicate handler for the route is not allowed. | Use a different handler. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_route_handler_not_fn">FST_ERR_ROUTE_HANDLER_NOT_FN</a> | Handler for the route must be a function. | Use a function for the handler. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_route_missing_handler">FST_ERR_ROUTE_MISSING_HANDLER</a> | Missing handler function for the route. | Add a handler function. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_route_method_invalid">FST_ERR_ROUTE_METHOD_INVALID</a> | Method is not a valid value. | Use a valid value for the method. | [#4750](https://github.com/fastify/fastify/pull/4750) |
|
||||
| <a id="fst_err_route_method_not_supported">FST_ERR_ROUTE_METHOD_NOT_SUPPORTED</a> | Method is not supported for the route. | Use a supported method. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_route_body_validation_schema_not_supported">FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED</a> | Body validation schema route is not supported. | Use a different different method for the route. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_route_body_limit_option_not_int">FST_ERR_ROUTE_BODY_LIMIT_OPTION_NOT_INT</a> | `bodyLimit` option must be an integer. | Use an integer for the `bodyLimit` option. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_route_rewrite_not_str">FST_ERR_ROUTE_REWRITE_NOT_STR</a> | `rewriteUrl` needs to be of type `string`. | Use a string for the `rewriteUrl`. | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_reopened_close_server">FST_ERR_REOPENED_CLOSE_SERVER</a> | Fastify has already been closed and cannot be reopened. | - | [#2415](https://github.com/fastify/fastify/pull/2415) |
|
||||
| <a id="fst_err_reopened_server">FST_ERR_REOPENED_SERVER</a> | Fastify is already listening. | - | [#2415](https://github.com/fastify/fastify/pull/2415) |
|
||||
| <a id="fst_err_plugin_version_mismatch">FST_ERR_PLUGIN_VERSION_MISMATCH</a> | Installed Fastify plugin mismatched expected version. | Use a compatible version of the plugin. | [#2549](https://github.com/fastify/fastify/pull/2549) |
|
||||
| <a id="fst_err_plugin_callback_not_fn">FST_ERR_PLUGIN_CALLBACK_NOT_FN</a> | Callback for a hook is not a function. | Use a function for the callback. | [#3106](https://github.com/fastify/fastify/pull/3106) |
|
||||
| <a id="fst_err_plugin_not_valid">FST_ERR_PLUGIN_NOT_VALID</a> | Plugin must be a function or a promise. | Use a function or a promise for the plugin. | [#3106](https://github.com/fastify/fastify/pull/3106) |
|
||||
| <a id="fst_err_root_plg_booted">FST_ERR_ROOT_PLG_BOOTED</a> | Root plugin has already booted. | - | [#3106](https://github.com/fastify/fastify/pull/3106) |
|
||||
| <a id="fst_err_parent_plugin_booted">FST_ERR_PARENT_PLUGIN_BOOTED</a> | Impossible to load plugin because the parent (mapped directly from `avvio`) | - | [#3106](https://github.com/fastify/fastify/pull/3106) |
|
||||
| <a id="fst_err_plugin_timeout">FST_ERR_PLUGIN_TIMEOUT</a> | Plugin did not start in time. | Increase the timeout for the plugin. | [#3106](https://github.com/fastify/fastify/pull/3106) |
|
||||
| <a id="fst_err_plugin_not_present_in_instance">FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE</a> | The decorator is not present in the instance. | - | [#4554](https://github.com/fastify/fastify/pull/4554) |
|
||||
| <a id="fst_err_validation">FST_ERR_VALIDATION</a> | The Request failed the payload validation. | Check the request payload. | [#4824](https://github.com/fastify/fastify/pull/4824) |
|
||||
| <a id="fst_err_listen_options_invalid">FST_ERR_LISTEN_OPTIONS_INVALID</a> | Invalid listen options. | Check the listen options. | [#4886](https://github.com/fastify/fastify/pull/4886) |
|
||||
| <a id="fst_err_error_handler_not_fn">FST_ERR_ERROR_HANDLER_NOT_FN</a> | Error Handler must be a function | Provide a function to `setErrorHandler`. | [#5317](https://github.com/fastify/fastify/pull/5317) |
|
||||
|
||||
94
backend/node_modules/fastify/docs/Reference/HTTP2.md
generated
vendored
Normal file
94
backend/node_modules/fastify/docs/Reference/HTTP2.md
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## HTTP2
|
||||
|
||||
_Fastify_ supports HTTP2 over either HTTPS (h2) or plaintext (h2c).
|
||||
|
||||
Currently, none of the HTTP2-specific APIs are available through _Fastify_, but
|
||||
Node's `req` and `res` can be accessed through our `Request` and `Reply`
|
||||
interface. PRs are welcome.
|
||||
|
||||
### Secure (HTTPS)
|
||||
|
||||
HTTP2 is supported in all modern browsers __only over a secure connection__:
|
||||
|
||||
```js
|
||||
'use strict'
|
||||
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const fastify = require('fastify')({
|
||||
http2: true,
|
||||
https: {
|
||||
key: fs.readFileSync(path.join(__dirname, '..', 'https', 'fastify.key')),
|
||||
cert: fs.readFileSync(path.join(__dirname, '..', 'https', 'fastify.cert'))
|
||||
}
|
||||
})
|
||||
|
||||
fastify.get('/', function (request, reply) {
|
||||
reply.code(200).send({ hello: 'world' })
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
[ALPN negotiation](https://datatracker.ietf.org/doc/html/rfc7301) allows
|
||||
support for both HTTPS and HTTP/2 over the same socket.
|
||||
Node core `req` and `res` objects can be either
|
||||
[HTTP/1](https://nodejs.org/api/http.html) or
|
||||
[HTTP/2](https://nodejs.org/api/http2.html). _Fastify_ supports this out of the
|
||||
box:
|
||||
|
||||
```js
|
||||
'use strict'
|
||||
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const fastify = require('fastify')({
|
||||
http2: true,
|
||||
https: {
|
||||
allowHTTP1: true, // fallback support for HTTP1
|
||||
key: fs.readFileSync(path.join(__dirname, '..', 'https', 'fastify.key')),
|
||||
cert: fs.readFileSync(path.join(__dirname, '..', 'https', 'fastify.cert'))
|
||||
}
|
||||
})
|
||||
|
||||
// this route can be accessed through both protocols
|
||||
fastify.get('/', function (request, reply) {
|
||||
reply.code(200).send({ hello: 'world' })
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
You can test your new server with:
|
||||
|
||||
```
|
||||
$ npx h2url https://localhost:3000
|
||||
```
|
||||
|
||||
### Plain or insecure
|
||||
|
||||
If you are building microservices, you can connect to HTTP2 in plain text,
|
||||
however, this is not supported by browsers.
|
||||
|
||||
```js
|
||||
'use strict'
|
||||
|
||||
const fastify = require('fastify')({
|
||||
http2: true
|
||||
})
|
||||
|
||||
fastify.get('/', function (request, reply) {
|
||||
reply.code(200).send({ hello: 'world' })
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
You can test your new server with:
|
||||
|
||||
```
|
||||
$ npx h2url http://localhost:3000
|
||||
```
|
||||
|
||||
869
backend/node_modules/fastify/docs/Reference/Hooks.md
generated
vendored
Normal file
869
backend/node_modules/fastify/docs/Reference/Hooks.md
generated
vendored
Normal file
@@ -0,0 +1,869 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Hooks
|
||||
|
||||
Hooks are registered with the `fastify.addHook` method and allow you to listen
|
||||
to specific events in the application or request/response lifecycle. You have to
|
||||
register a hook before the event is triggered, otherwise, the event is lost.
|
||||
|
||||
By using hooks you can interact directly with the lifecycle of Fastify. There
|
||||
are Request/Reply hooks and application hooks:
|
||||
|
||||
- [Request/Reply Hooks](#requestreply-hooks)
|
||||
- [onRequest](#onrequest)
|
||||
- [preParsing](#preparsing)
|
||||
- [preValidation](#prevalidation)
|
||||
- [preHandler](#prehandler)
|
||||
- [preSerialization](#preserialization)
|
||||
- [onError](#onerror)
|
||||
- [onSend](#onsend)
|
||||
- [onResponse](#onresponse)
|
||||
- [onTimeout](#ontimeout)
|
||||
- [onRequestAbort](#onrequestabort)
|
||||
- [Manage Errors from a hook](#manage-errors-from-a-hook)
|
||||
- [Respond to a request from a hook](#respond-to-a-request-from-a-hook)
|
||||
- [Application Hooks](#application-hooks)
|
||||
- [onReady](#onready)
|
||||
- [onListen](#onlisten)
|
||||
- [onClose](#onclose)
|
||||
- [preClose](#preclose)
|
||||
- [onRoute](#onroute)
|
||||
- [onRegister](#onregister)
|
||||
- [Scope](#scope)
|
||||
- [Route level hooks](#route-level-hooks)
|
||||
- [Using Hooks to Inject Custom Properties](#using-hooks-to-inject-custom-properties)
|
||||
- [Diagnostics Channel Hooks](#diagnostics-channel-hooks)
|
||||
|
||||
**Notice:** the `done` callback is not available when using `async`/`await` or
|
||||
returning a `Promise`. If you do invoke a `done` callback in this situation
|
||||
unexpected behavior may occur, e.g. duplicate invocation of handlers.
|
||||
|
||||
## Request/Reply Hooks
|
||||
|
||||
[Request](./Request.md) and [Reply](./Reply.md) are the core Fastify objects.
|
||||
|
||||
`done` is the function to continue with the [lifecycle](./Lifecycle.md).
|
||||
|
||||
It is easy to understand where each hook is executed by looking at the
|
||||
[lifecycle page](./Lifecycle.md).
|
||||
|
||||
Hooks are affected by Fastify's encapsulation, and can thus be applied to
|
||||
selected routes. See the [Scopes](#scope) section for more information.
|
||||
|
||||
There are eight different hooks that you can use in Request/Reply *(in order of
|
||||
execution)*:
|
||||
|
||||
### onRequest
|
||||
```js
|
||||
fastify.addHook('onRequest', (request, reply, done) => {
|
||||
// Some code
|
||||
done()
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('onRequest', async (request, reply) => {
|
||||
// Some code
|
||||
await asyncMethod()
|
||||
})
|
||||
```
|
||||
|
||||
**Notice:** in the [onRequest](#onrequest) hook, `request.body` will always be
|
||||
`undefined`, because the body parsing happens before the
|
||||
[preValidation](#prevalidation) hook.
|
||||
|
||||
### preParsing
|
||||
|
||||
If you are using the `preParsing` hook, you can transform the request payload
|
||||
stream before it is parsed. It receives the request and reply objects as other
|
||||
hooks, and a stream with the current request payload.
|
||||
|
||||
If it returns a value (via `return` or via the callback function), it must
|
||||
return a stream.
|
||||
|
||||
For instance, you can decompress the request body:
|
||||
|
||||
```js
|
||||
fastify.addHook('preParsing', (request, reply, payload, done) => {
|
||||
// Some code
|
||||
done(null, newPayload)
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('preParsing', async (request, reply, payload) => {
|
||||
// Some code
|
||||
await asyncMethod()
|
||||
return newPayload
|
||||
})
|
||||
```
|
||||
|
||||
**Notice:** in the [preParsing](#preparsing) hook, `request.body` will always be
|
||||
`undefined`, because the body parsing happens before the
|
||||
[preValidation](#prevalidation) hook.
|
||||
|
||||
**Notice:** you should also add a `receivedEncodedLength` property to the
|
||||
returned stream. This property is used to correctly match the request payload
|
||||
with the `Content-Length` header value. Ideally, this property should be updated
|
||||
on each received chunk.
|
||||
|
||||
**Notice:** The size of the returned stream is checked to not exceed the limit
|
||||
set in [`bodyLimit`](./Server.md#bodylimit) option.
|
||||
|
||||
### preValidation
|
||||
|
||||
If you are using the `preValidation` hook, you can change the payload before it
|
||||
is validated. For example:
|
||||
|
||||
```js
|
||||
fastify.addHook('preValidation', (request, reply, done) => {
|
||||
request.body = { ...request.body, importantKey: 'randomString' }
|
||||
done()
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('preValidation', async (request, reply) => {
|
||||
const importantKey = await generateRandomString()
|
||||
request.body = { ...request.body, importantKey }
|
||||
})
|
||||
```
|
||||
|
||||
### preHandler
|
||||
|
||||
The `preHandler` hook allows you to specify a function that is executed before
|
||||
a routes's handler.
|
||||
|
||||
```js
|
||||
fastify.addHook('preHandler', (request, reply, done) => {
|
||||
// some code
|
||||
done()
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('preHandler', async (request, reply) => {
|
||||
// Some code
|
||||
await asyncMethod()
|
||||
})
|
||||
```
|
||||
### preSerialization
|
||||
|
||||
If you are using the `preSerialization` hook, you can change (or replace) the
|
||||
payload before it is serialized. For example:
|
||||
|
||||
```js
|
||||
fastify.addHook('preSerialization', (request, reply, payload, done) => {
|
||||
const err = null
|
||||
const newPayload = { wrapped: payload }
|
||||
done(err, newPayload)
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('preSerialization', async (request, reply, payload) => {
|
||||
return { wrapped: payload }
|
||||
})
|
||||
```
|
||||
|
||||
Note: the hook is NOT called if the payload is a `string`, a `Buffer`, a
|
||||
`stream`, or `null`.
|
||||
|
||||
### onError
|
||||
```js
|
||||
fastify.addHook('onError', (request, reply, error, done) => {
|
||||
// Some code
|
||||
done()
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('onError', async (request, reply, error) => {
|
||||
// Useful for custom error logging
|
||||
// You should not use this hook to update the error
|
||||
})
|
||||
```
|
||||
This hook is useful if you need to do some custom error logging or add some
|
||||
specific header in case of error.
|
||||
|
||||
It is not intended for changing the error, and calling `reply.send` will throw
|
||||
an exception.
|
||||
|
||||
This hook will be executed only after
|
||||
the [Custom Error Handler set by `setErrorHandler`](./Server.md#seterrorhandler)
|
||||
has been executed, and only if the custom error handler sends an error back to the
|
||||
user
|
||||
*(Note that the default error handler always sends the error back to the
|
||||
user)*.
|
||||
|
||||
**Notice:** unlike the other hooks, passing an error to the `done` function is not
|
||||
supported.
|
||||
|
||||
### onSend
|
||||
If you are using the `onSend` hook, you can change the payload. For example:
|
||||
|
||||
```js
|
||||
fastify.addHook('onSend', (request, reply, payload, done) => {
|
||||
const err = null;
|
||||
const newPayload = payload.replace('some-text', 'some-new-text')
|
||||
done(err, newPayload)
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('onSend', async (request, reply, payload) => {
|
||||
const newPayload = payload.replace('some-text', 'some-new-text')
|
||||
return newPayload
|
||||
})
|
||||
```
|
||||
|
||||
You can also clear the payload to send a response with an empty body by
|
||||
replacing the payload with `null`:
|
||||
|
||||
```js
|
||||
fastify.addHook('onSend', (request, reply, payload, done) => {
|
||||
reply.code(304)
|
||||
const newPayload = null
|
||||
done(null, newPayload)
|
||||
})
|
||||
```
|
||||
|
||||
> You can also send an empty body by replacing the payload with the empty string
|
||||
> `''`, but be aware that this will cause the `Content-Length` header to be set
|
||||
> to `0`, whereas the `Content-Length` header will not be set if the payload is
|
||||
> `null`.
|
||||
|
||||
Note: If you change the payload, you may only change it to a `string`, a
|
||||
`Buffer`, a `stream`, a `ReadableStream`, a `Response`, or `null`.
|
||||
|
||||
|
||||
### onResponse
|
||||
```js
|
||||
fastify.addHook('onResponse', (request, reply, done) => {
|
||||
// Some code
|
||||
done()
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('onResponse', async (request, reply) => {
|
||||
// Some code
|
||||
await asyncMethod()
|
||||
})
|
||||
```
|
||||
|
||||
The `onResponse` hook is executed when a response has been sent, so you will not
|
||||
be able to send more data to the client. It can however be useful for sending
|
||||
data to external services, for example, to gather statistics.
|
||||
|
||||
**Note:** setting `disableRequestLogging` to `true` will disable any error log
|
||||
inside the `onResponse` hook. In this case use `try - catch` to log errors.
|
||||
|
||||
### onTimeout
|
||||
|
||||
```js
|
||||
fastify.addHook('onTimeout', (request, reply, done) => {
|
||||
// Some code
|
||||
done()
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('onTimeout', async (request, reply) => {
|
||||
// Some code
|
||||
await asyncMethod()
|
||||
})
|
||||
```
|
||||
`onTimeout` is useful if you need to monitor the request timed out in your
|
||||
service (if the `connectionTimeout` property is set on the Fastify instance).
|
||||
The `onTimeout` hook is executed when a request is timed out and the HTTP socket
|
||||
has been hung up. Therefore, you will not be able to send data to the client.
|
||||
|
||||
### onRequestAbort
|
||||
|
||||
```js
|
||||
fastify.addHook('onRequestAbort', (request, done) => {
|
||||
// Some code
|
||||
done()
|
||||
})
|
||||
```
|
||||
Or `async/await`:
|
||||
```js
|
||||
fastify.addHook('onRequestAbort', async (request) => {
|
||||
// Some code
|
||||
await asyncMethod()
|
||||
})
|
||||
```
|
||||
The `onRequestAbort` hook is executed when a client closes the connection before
|
||||
the entire request has been processed. Therefore, you will not be able to send
|
||||
data to the client.
|
||||
|
||||
**Notice:** client abort detection is not completely reliable. See: [`Detecting-When-Clients-Abort.md`](../Guides/Detecting-When-Clients-Abort.md)
|
||||
|
||||
### Manage Errors from a hook
|
||||
If you get an error during the execution of your hook, just pass it to `done()`
|
||||
and Fastify will automatically close the request and send the appropriate error
|
||||
code to the user.
|
||||
|
||||
```js
|
||||
fastify.addHook('onRequest', (request, reply, done) => {
|
||||
done(new Error('Some error'))
|
||||
})
|
||||
```
|
||||
|
||||
If you want to pass a custom error code to the user, just use `reply.code()`:
|
||||
```js
|
||||
fastify.addHook('preHandler', (request, reply, done) => {
|
||||
reply.code(400)
|
||||
done(new Error('Some error'))
|
||||
})
|
||||
```
|
||||
*The error will be handled by [`Reply`](./Reply.md#errors).*
|
||||
|
||||
Or if you're using `async/await` you can just throw an error:
|
||||
```js
|
||||
fastify.addHook('onRequest', async (request, reply) => {
|
||||
throw new Error('Some error')
|
||||
})
|
||||
```
|
||||
|
||||
### Respond to a request from a hook
|
||||
|
||||
If needed, you can respond to a request before you reach the route handler, for
|
||||
example when implementing an authentication hook. Replying from a hook implies
|
||||
that the hook chain is __stopped__ and the rest of the hooks and handlers are
|
||||
not executed. If the hook is using the callback approach, i.e. it is not an
|
||||
`async` function or it returns a `Promise`, it is as simple as calling
|
||||
`reply.send()` and avoiding calling the callback. If the hook is `async`,
|
||||
`reply.send()` __must__ be called _before_ the function returns or the promise
|
||||
resolves, otherwise, the request will proceed. When `reply.send()` is called
|
||||
outside of the promise chain, it is important to `return reply` otherwise the
|
||||
request will be executed twice.
|
||||
|
||||
It is important to __not mix callbacks and `async`/`Promise`__, otherwise the
|
||||
hook chain will be executed twice.
|
||||
|
||||
If you are using `onRequest` or `preHandler` use `reply.send`.
|
||||
|
||||
```js
|
||||
fastify.addHook('onRequest', (request, reply, done) => {
|
||||
reply.send('Early response')
|
||||
})
|
||||
|
||||
// Works with async functions too
|
||||
fastify.addHook('preHandler', async (request, reply) => {
|
||||
setTimeout(() => {
|
||||
reply.send({ hello: 'from prehandler' })
|
||||
})
|
||||
return reply // mandatory, so the request is not executed further
|
||||
// Commenting the line above will allow the hooks to continue and fail with FST_ERR_REP_ALREADY_SENT
|
||||
})
|
||||
```
|
||||
|
||||
If you want to respond with a stream, you should avoid using an `async` function
|
||||
for the hook. If you must use an `async` function, your code will need to follow
|
||||
the pattern in
|
||||
[test/hooks-async.js](https://github.com/fastify/fastify/blob/94ea67ef2d8dce8a955d510cd9081aabd036fa85/test/hooks-async.js#L269-L275).
|
||||
|
||||
```js
|
||||
fastify.addHook('onRequest', (request, reply, done) => {
|
||||
const stream = fs.createReadStream('some-file', 'utf8')
|
||||
reply.send(stream)
|
||||
})
|
||||
```
|
||||
|
||||
If you are sending a response without `await` on it, make sure to always `return
|
||||
reply`:
|
||||
|
||||
```js
|
||||
fastify.addHook('preHandler', async (request, reply) => {
|
||||
setImmediate(() => { reply.send('hello') })
|
||||
|
||||
// This is needed to signal the handler to wait for a response
|
||||
// to be sent outside of the promise chain
|
||||
return reply
|
||||
})
|
||||
|
||||
fastify.addHook('preHandler', async (request, reply) => {
|
||||
// the @fastify/static plugin will send a file asynchronously,
|
||||
// so we should return reply
|
||||
reply.sendFile('myfile')
|
||||
return reply
|
||||
})
|
||||
```
|
||||
|
||||
## Application Hooks
|
||||
|
||||
You can hook into the application-lifecycle as well.
|
||||
|
||||
- [onReady](#onready)
|
||||
- [onListen](#onlisten)
|
||||
- [onClose](#onclose)
|
||||
- [preClose](#preclose)
|
||||
- [onRoute](#onroute)
|
||||
- [onRegister](#onregister)
|
||||
|
||||
### onReady
|
||||
Triggered before the server starts listening for requests and when `.ready()` is
|
||||
invoked. It cannot change the routes or add new hooks. Registered hook functions
|
||||
are executed serially. Only after all `onReady` hook functions have completed
|
||||
will the server start listening for requests. Hook functions accept one
|
||||
argument: a callback, `done`, to be invoked after the hook function is complete.
|
||||
Hook functions are invoked with `this` bound to the associated Fastify instance.
|
||||
|
||||
```js
|
||||
// callback style
|
||||
fastify.addHook('onReady', function (done) {
|
||||
// Some code
|
||||
const err = null;
|
||||
done(err)
|
||||
})
|
||||
|
||||
// or async/await style
|
||||
fastify.addHook('onReady', async function () {
|
||||
// Some async code
|
||||
await loadCacheFromDatabase()
|
||||
})
|
||||
```
|
||||
|
||||
### onListen
|
||||
|
||||
Triggered when the server starts listening for requests. The hooks run one
|
||||
after another. If a hook function causes an error, it is logged and
|
||||
ignored, allowing the queue of hooks to continue. Hook functions accept one
|
||||
argument: a callback, `done`, to be invoked after the hook function is
|
||||
complete. Hook functions are invoked with `this` bound to the associated
|
||||
Fastify instance.
|
||||
|
||||
This is an alternative to `fastify.server.on('listening', () => {})`.
|
||||
|
||||
```js
|
||||
// callback style
|
||||
fastify.addHook('onListen', function (done) {
|
||||
// Some code
|
||||
const err = null;
|
||||
done(err)
|
||||
})
|
||||
|
||||
// or async/await style
|
||||
fastify.addHook('onListen', async function () {
|
||||
// Some async code
|
||||
})
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> This hook will not run when the server is started using `fastify.inject()` or `fastify.ready()`
|
||||
|
||||
### onClose
|
||||
<a id="on-close"></a>
|
||||
|
||||
Triggered when `fastify.close()` is invoked to stop the server, after all in-flight
|
||||
HTTP requests have been completed.
|
||||
It is useful when [plugins](./Plugins.md) need a "shutdown" event, for example,
|
||||
to close an open connection to a database.
|
||||
|
||||
The hook function takes the Fastify instance as a first argument,
|
||||
and a `done` callback for synchronous hook functions.
|
||||
```js
|
||||
// callback style
|
||||
fastify.addHook('onClose', (instance, done) => {
|
||||
// Some code
|
||||
done()
|
||||
})
|
||||
|
||||
// or async/await style
|
||||
fastify.addHook('onClose', async (instance) => {
|
||||
// Some async code
|
||||
await closeDatabaseConnections()
|
||||
})
|
||||
```
|
||||
|
||||
### preClose
|
||||
<a id="pre-close"></a>
|
||||
|
||||
Triggered when `fastify.close()` is invoked to stop the server, before all in-flight
|
||||
HTTP requests have been completed.
|
||||
It is useful when [plugins](./Plugins.md) have set up some state attached
|
||||
to the HTTP server that would prevent the server to close.
|
||||
_It is unlikely you will need to use this hook_,
|
||||
use the [`onClose`](#onclose) for the most common case.
|
||||
|
||||
```js
|
||||
// callback style
|
||||
fastify.addHook('preClose', (done) => {
|
||||
// Some code
|
||||
done()
|
||||
})
|
||||
|
||||
// or async/await style
|
||||
fastify.addHook('preClose', async () => {
|
||||
// Some async code
|
||||
await removeSomeServerState()
|
||||
})
|
||||
```
|
||||
|
||||
### onRoute
|
||||
<a id="on-route"></a>
|
||||
|
||||
Triggered when a new route is registered. Listeners are passed a [`routeOptions`](./Routes.md#routes-options)
|
||||
object as the sole parameter. The interface is synchronous, and, as such, the
|
||||
listeners are not passed a callback. This hook is encapsulated.
|
||||
|
||||
```js
|
||||
fastify.addHook('onRoute', (routeOptions) => {
|
||||
//Some code
|
||||
routeOptions.method
|
||||
routeOptions.schema
|
||||
routeOptions.url // the complete URL of the route, it will include the prefix if any
|
||||
routeOptions.path // `url` alias
|
||||
routeOptions.routePath // the URL of the route without the prefix
|
||||
routeOptions.bodyLimit
|
||||
routeOptions.logLevel
|
||||
routeOptions.logSerializers
|
||||
routeOptions.prefix
|
||||
})
|
||||
```
|
||||
|
||||
If you are authoring a plugin and you need to customize application routes, like
|
||||
modifying the options or adding new route hooks, this is the right place.
|
||||
|
||||
```js
|
||||
fastify.addHook('onRoute', (routeOptions) => {
|
||||
function onPreSerialization(request, reply, payload, done) {
|
||||
// Your code
|
||||
done(null, payload)
|
||||
}
|
||||
// preSerialization can be an array or undefined
|
||||
routeOptions.preSerialization = [...(routeOptions.preSerialization || []), onPreSerialization]
|
||||
})
|
||||
```
|
||||
|
||||
To add more routes within an onRoute hook, the routes must
|
||||
be tagged correctly. The hook will run into an infinite loop if
|
||||
not tagged. The recommended approach is shown below.
|
||||
|
||||
```js
|
||||
const kRouteAlreadyProcessed = Symbol('route-already-processed')
|
||||
|
||||
fastify.addHook('onRoute', function (routeOptions) {
|
||||
const { url, method } = routeOptions
|
||||
|
||||
const isAlreadyProcessed = (routeOptions.custom && routeOptions.custom[kRouteAlreadyProcessed]) || false
|
||||
|
||||
if (!isAlreadyProcessed) {
|
||||
this.route({
|
||||
url,
|
||||
method,
|
||||
custom: {
|
||||
[kRouteAlreadyProcessed]: true
|
||||
},
|
||||
handler: () => {}
|
||||
})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
For more details, see this [issue](https://github.com/fastify/fastify/issues/4319).
|
||||
|
||||
### onRegister
|
||||
<a id="on-register"></a>
|
||||
|
||||
Triggered when a new plugin is registered and a new encapsulation context is
|
||||
created. The hook will be executed **before** the registered code.
|
||||
|
||||
This hook can be useful if you are developing a plugin that needs to know when a
|
||||
plugin context is formed, and you want to operate in that specific context, thus
|
||||
this hook is encapsulated.
|
||||
|
||||
**Note:** This hook will not be called if a plugin is wrapped inside
|
||||
[`fastify-plugin`](https://github.com/fastify/fastify-plugin).
|
||||
```js
|
||||
fastify.decorate('data', [])
|
||||
|
||||
fastify.register(async (instance, opts) => {
|
||||
instance.data.push('hello')
|
||||
console.log(instance.data) // ['hello']
|
||||
|
||||
instance.register(async (instance, opts) => {
|
||||
instance.data.push('world')
|
||||
console.log(instance.data) // ['hello', 'world']
|
||||
}, { prefix: '/hola' })
|
||||
}, { prefix: '/ciao' })
|
||||
|
||||
fastify.register(async (instance, opts) => {
|
||||
console.log(instance.data) // []
|
||||
}, { prefix: '/hello' })
|
||||
|
||||
fastify.addHook('onRegister', (instance, opts) => {
|
||||
// Create a new array from the old one
|
||||
// but without keeping the reference
|
||||
// allowing the user to have encapsulated
|
||||
// instances of the `data` property
|
||||
instance.data = instance.data.slice()
|
||||
|
||||
// the options of the new registered instance
|
||||
console.log(opts.prefix)
|
||||
})
|
||||
```
|
||||
|
||||
## Scope
|
||||
<a id="scope"></a>
|
||||
|
||||
Except for [onClose](#onclose), all hooks are encapsulated. This means that you
|
||||
can decide where your hooks should run by using `register` as explained in the
|
||||
[plugins guide](../Guides/Plugins-Guide.md). If you pass a function, that
|
||||
function is bound to the right Fastify context and from there you have full
|
||||
access to the Fastify API.
|
||||
|
||||
```js
|
||||
fastify.addHook('onRequest', function (request, reply, done) {
|
||||
const self = this // Fastify context
|
||||
done()
|
||||
})
|
||||
```
|
||||
|
||||
Note that the Fastify context in each hook is the same as the plugin where the
|
||||
route was registered, for example:
|
||||
|
||||
```js
|
||||
fastify.addHook('onRequest', async function (req, reply) {
|
||||
if (req.raw.url === '/nested') {
|
||||
assert.strictEqual(this.foo, 'bar')
|
||||
} else {
|
||||
assert.strictEqual(this.foo, undefined)
|
||||
}
|
||||
})
|
||||
|
||||
fastify.get('/', async function (req, reply) {
|
||||
assert.strictEqual(this.foo, undefined)
|
||||
return { hello: 'world' }
|
||||
})
|
||||
|
||||
fastify.register(async function plugin (fastify, opts) {
|
||||
fastify.decorate('foo', 'bar')
|
||||
|
||||
fastify.get('/nested', async function (req, reply) {
|
||||
assert.strictEqual(this.foo, 'bar')
|
||||
return { hello: 'world' }
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Warn: if you declare the function with an [arrow
|
||||
function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions),
|
||||
the `this` will not be Fastify, but the one of the current scope.
|
||||
|
||||
|
||||
## Route level hooks
|
||||
<a id="route-hooks"></a>
|
||||
|
||||
You can declare one or more custom lifecycle hooks ([onRequest](#onrequest),
|
||||
[onResponse](#onresponse), [preParsing](#preparsing),
|
||||
[preValidation](#prevalidation), [preHandler](#prehandler),
|
||||
[preSerialization](#preserialization), [onSend](#onsend),
|
||||
[onTimeout](#ontimeout), and [onError](#onerror)) hook(s) that will be
|
||||
**unique** for the route. If you do so, those hooks are always executed as the
|
||||
last hook in their category.
|
||||
|
||||
This can be useful if you need to implement authentication, where the
|
||||
[preParsing](#preparsing) or [preValidation](#prevalidation) hooks are exactly
|
||||
what you need. Multiple route-level hooks can also be specified as an array.
|
||||
|
||||
```js
|
||||
fastify.addHook('onRequest', (request, reply, done) => {
|
||||
// Your code
|
||||
done()
|
||||
})
|
||||
|
||||
fastify.addHook('onResponse', (request, reply, done) => {
|
||||
// your code
|
||||
done()
|
||||
})
|
||||
|
||||
fastify.addHook('preParsing', (request, reply, done) => {
|
||||
// Your code
|
||||
done()
|
||||
})
|
||||
|
||||
fastify.addHook('preValidation', (request, reply, done) => {
|
||||
// Your code
|
||||
done()
|
||||
})
|
||||
|
||||
fastify.addHook('preHandler', (request, reply, done) => {
|
||||
// Your code
|
||||
done()
|
||||
})
|
||||
|
||||
fastify.addHook('preSerialization', (request, reply, payload, done) => {
|
||||
// Your code
|
||||
done(null, payload)
|
||||
})
|
||||
|
||||
fastify.addHook('onSend', (request, reply, payload, done) => {
|
||||
// Your code
|
||||
done(null, payload)
|
||||
})
|
||||
|
||||
fastify.addHook('onTimeout', (request, reply, done) => {
|
||||
// Your code
|
||||
done()
|
||||
})
|
||||
|
||||
fastify.addHook('onError', (request, reply, error, done) => {
|
||||
// Your code
|
||||
done()
|
||||
})
|
||||
|
||||
fastify.route({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
schema: { ... },
|
||||
onRequest: function (request, reply, done) {
|
||||
// This hook will always be executed after the shared `onRequest` hooks
|
||||
done()
|
||||
},
|
||||
// // Example with an async hook. All hooks support this syntax
|
||||
//
|
||||
// onRequest: async function (request, reply) {
|
||||
// // This hook will always be executed after the shared `onRequest` hooks
|
||||
// await ...
|
||||
// }
|
||||
onResponse: function (request, reply, done) {
|
||||
// this hook will always be executed after the shared `onResponse` hooks
|
||||
done()
|
||||
},
|
||||
preParsing: function (request, reply, done) {
|
||||
// This hook will always be executed after the shared `preParsing` hooks
|
||||
done()
|
||||
},
|
||||
preValidation: function (request, reply, done) {
|
||||
// This hook will always be executed after the shared `preValidation` hooks
|
||||
done()
|
||||
},
|
||||
preHandler: function (request, reply, done) {
|
||||
// This hook will always be executed after the shared `preHandler` hooks
|
||||
done()
|
||||
},
|
||||
// // Example with an array. All hooks support this syntax.
|
||||
//
|
||||
// preHandler: [function (request, reply, done) {
|
||||
// // This hook will always be executed after the shared `preHandler` hooks
|
||||
// done()
|
||||
// }],
|
||||
preSerialization: (request, reply, payload, done) => {
|
||||
// This hook will always be executed after the shared `preSerialization` hooks
|
||||
done(null, payload)
|
||||
},
|
||||
onSend: (request, reply, payload, done) => {
|
||||
// This hook will always be executed after the shared `onSend` hooks
|
||||
done(null, payload)
|
||||
},
|
||||
onTimeout: (request, reply, done) => {
|
||||
// This hook will always be executed after the shared `onTimeout` hooks
|
||||
done()
|
||||
},
|
||||
onError: (request, reply, error, done) => {
|
||||
// This hook will always be executed after the shared `onError` hooks
|
||||
done()
|
||||
},
|
||||
handler: function (request, reply) {
|
||||
reply.send({ hello: 'world' })
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**Note**: both options also accept an array of functions.
|
||||
|
||||
## Using Hooks to Inject Custom Properties
|
||||
<a id="using-hooks-to-inject-custom-properties"></a>
|
||||
|
||||
You can use a hook to inject custom properties into incoming requests.
|
||||
This is useful for reusing processed data from hooks in controllers.
|
||||
|
||||
A very common use case is, for example, checking user authentication based
|
||||
on their token and then storing their recovered data into
|
||||
the [Request](./Request.md) instance. This way, your controllers can read it
|
||||
easily with `request.authenticatedUser` or whatever you want to call it.
|
||||
That's how it might look like:
|
||||
|
||||
```js
|
||||
fastify.addHook('preParsing', async (request) => {
|
||||
request.authenticatedUser = {
|
||||
id: 42,
|
||||
name: 'Jane Doe',
|
||||
role: 'admin'
|
||||
}
|
||||
})
|
||||
|
||||
fastify.get('/me/is-admin', async function (req, reply) {
|
||||
return { isAdmin: req.authenticatedUser?.role === 'admin' || false }
|
||||
})
|
||||
```
|
||||
|
||||
Note that `.authenticatedUser` could actually be any property name
|
||||
chosen by yourself. Using your own custom property prevents you
|
||||
from mutating existing properties, which
|
||||
would be a dangerous and destructive operation. So be careful and
|
||||
make sure your property is entirely new, also using this approach
|
||||
only for very specific and small cases like this example.
|
||||
|
||||
Regarding TypeScript in this example, you'd need to update the
|
||||
`FastifyRequest` core interface to include your new property typing
|
||||
(for more about it, see [TypeScript](./TypeScript.md) page), like:
|
||||
|
||||
```ts
|
||||
interface AuthenticatedUser { /* ... */ }
|
||||
|
||||
declare module 'fastify' {
|
||||
export interface FastifyRequest {
|
||||
authenticatedUser?: AuthenticatedUser;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Although this is a very pragmatic approach, if you're trying to do
|
||||
something more complex that changes these core objects, then
|
||||
consider creating a custom [Plugin](./Plugins.md) instead.
|
||||
|
||||
## Diagnostics Channel Hooks
|
||||
|
||||
> **Note:** The `diagnostics_channel` is currently experimental on Node.js, so
|
||||
> its API is subject to change even in semver-patch releases of Node.js. For
|
||||
> versions of Node.js supported by Fastify where `diagnostics_channel` is
|
||||
> unavailable, the hook will use the
|
||||
> [polyfill](https://www.npmjs.com/package/diagnostics_channel) if it is
|
||||
> available. Otherwise, this feature will not be present.
|
||||
|
||||
Currently, one
|
||||
[`diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html) publish
|
||||
event, `'fastify.initialization'`, happens at initialization time. The Fastify
|
||||
instance is passed into the hook as a property of the object passed in. At this
|
||||
point, the instance can be interacted with to add hooks, plugins, routes, or any
|
||||
other sort of modification.
|
||||
|
||||
For example, a tracing package might do something like the following (which is,
|
||||
of course, a simplification). This would be in a file loaded in the
|
||||
initialization of the tracking package, in the typical "require instrumentation
|
||||
tools first" fashion.
|
||||
|
||||
```js
|
||||
const tracer = /* retrieved from elsewhere in the package */
|
||||
const dc = require('node:diagnostics_channel')
|
||||
const channel = dc.channel('fastify.initialization')
|
||||
const spans = new WeakMap()
|
||||
|
||||
channel.subscribe(function ({ fastify }) {
|
||||
fastify.addHook('onRequest', (request, reply, done) => {
|
||||
const span = tracer.startSpan('fastify.request')
|
||||
spans.set(request, span)
|
||||
done()
|
||||
})
|
||||
|
||||
fastify.addHook('onResponse', (request, reply, done) => {
|
||||
const span = spans.get(request)
|
||||
span.finish()
|
||||
done()
|
||||
})
|
||||
})
|
||||
```
|
||||
73
backend/node_modules/fastify/docs/Reference/Index.md
generated
vendored
Normal file
73
backend/node_modules/fastify/docs/Reference/Index.md
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Core Documents
|
||||
<a id="reference-core-docs"></a>
|
||||
|
||||
For the full table of contents (TOC), see [below](#reference-toc). The following
|
||||
list is a subset of the full TOC that detail core Fastify APIs and concepts in
|
||||
order of most likely importance to the reader:
|
||||
|
||||
+ [Server](./Server.md): Documents the core Fastify API. Includes documentation
|
||||
for the factory function and the object returned by the factory function.
|
||||
+ [Lifecycle](./Lifecycle.md): Explains the Fastify request lifecycle and
|
||||
illustrates where [Hooks](./Hooks.md) are available for integrating with it.
|
||||
+ [Routes](./Routes.md): Details how to register routes with Fastify and how
|
||||
Fastify builds and evaluates the routing trie.
|
||||
+ [Request](./Request.md): Details Fastify's request object that is passed into
|
||||
each request handler.
|
||||
+ [Reply](./Reply.md): Details Fastify's response object available to each
|
||||
request handler.
|
||||
+ [Validation and Serialization](./Validation-and-Serialization.md): Details
|
||||
Fastify's support for validating incoming data and how Fastify serializes data
|
||||
for responses.
|
||||
+ [Plugins](./Plugins.md): Explains Fastify's plugin architecture and API.
|
||||
+ [Encapsulation](./Encapsulation.md): Explains a core concept upon which all
|
||||
Fastify plugins are built.
|
||||
+ [Decorators](./Decorators.md): Explains the server, request, and response
|
||||
decorator APIs.
|
||||
+ [Hooks](./Hooks.md): Details the API by which Fastify plugins can inject
|
||||
themselves into Fastify's handling of the request lifecycle.
|
||||
|
||||
|
||||
## Reference Documentation Table Of Contents
|
||||
<a id="reference-toc"></a>
|
||||
|
||||
This table of contents is in alphabetical order.
|
||||
|
||||
+ [Content Type Parser](./ContentTypeParser.md): Documents Fastify's default
|
||||
content type parser and how to add support for new content types.
|
||||
+ [Decorators](./Decorators.md): Explains the server, request, and response
|
||||
decorator APIs.
|
||||
+ [Encapsulation](./Encapsulation.md): Explains a core concept upon which all
|
||||
Fastify plugins are built.
|
||||
+ [Errors](./Errors.md): Details how Fastify handles errors and lists the
|
||||
standard set of errors Fastify generates.
|
||||
+ [Hooks](./Hooks.md): Details the API by which Fastify plugins can inject
|
||||
themselves into Fastify's handling of the request lifecycle.
|
||||
+ [HTTP2](./HTTP2.md): Details Fastify's HTTP2 support.
|
||||
+ [Lifecycle](./Lifecycle.md): Explains the Fastify request lifecycle and
|
||||
illustrates where [Hooks](./Hooks.md) are available for integrating with it.
|
||||
+ [Logging](./Logging.md): Details Fastify's included logging and how to
|
||||
customize it.
|
||||
+ [Long Term Support](./LTS.md): Explains Fastify's long term support (LTS)
|
||||
guarantee and the exceptions possible to the [semver](https://semver.org)
|
||||
contract.
|
||||
+ [Middleware](./Middleware.md): Details Fastify's support for Express.js style
|
||||
middleware.
|
||||
+ [Plugins](./Plugins.md): Explains Fastify's plugin architecture and API.
|
||||
+ [Reply](./Reply.md): Details Fastify's response object available to each
|
||||
request handler.
|
||||
+ [Request](./Request.md): Details Fastify's request object that is passed into
|
||||
each request handler.
|
||||
+ [Routes](./Routes.md): Details how to register routes with Fastify and how
|
||||
Fastify builds and evaluates the routing trie.
|
||||
+ [Server](./Server.md): Documents the core Fastify API. Includes documentation
|
||||
for the factory function and the object returned by the factory function.
|
||||
+ [TypeScript](./TypeScript.md): Documents Fastify's TypeScript support and
|
||||
provides recommendations for writing applications in TypeScript that utilize
|
||||
Fastify.
|
||||
+ [Validation and Serialization](./Validation-and-Serialization.md): Details
|
||||
Fastify's support for validating incoming data and how Fastify serializes data
|
||||
for responses.
|
||||
+ [Warnings](./Warnings.md): Details the warnings Fastify emits and how to
|
||||
solve them.
|
||||
82
backend/node_modules/fastify/docs/Reference/LTS.md
generated
vendored
Normal file
82
backend/node_modules/fastify/docs/Reference/LTS.md
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Long Term Support
|
||||
|
||||
`<a id="lts"></a>`
|
||||
|
||||
Fastify's Long Term Support (LTS) is provided according to the schedule laid out
|
||||
in this document:
|
||||
|
||||
1. Major releases, "X" release of [semantic versioning][semver] X.Y.Z release
|
||||
versions, are supported for a minimum period of six months from their release
|
||||
date. The release date of any specific version can be found at
|
||||
[https://github.com/fastify/fastify/releases](https://github.com/fastify/fastify/releases).
|
||||
2. Major releases will receive security updates for an additional six months
|
||||
from the release of the next major release. After this period we will still
|
||||
review and release security fixes as long as they are provided by the
|
||||
community and they do not violate other constraints, e.g. minimum supported
|
||||
Node.js version.
|
||||
3. Major releases will be tested and verified against all Node.js release lines
|
||||
that are supported by the [Node.js LTS
|
||||
policy](https://github.com/nodejs/Release) within the LTS period of that
|
||||
given Fastify release line. This implies that only the latest Node.js release
|
||||
of a given line is supported.
|
||||
4. In addition to Node.js runtime, major releases of Fastify will also be tested
|
||||
and verified against alternative runtimes that are compatible with Node.js.
|
||||
The maintenance teams of these alternative runtimes are responsible for ensuring
|
||||
and guaranteeing these tests work properly.
|
||||
1. [N|Solid](https://docs.nodesource.com/nsolid), maintained by NodeSource,
|
||||
commits to testing and verifying each Fastify major release against the N|Solid
|
||||
LTS versions that are current at the time of the Fastify release.
|
||||
NodeSource guarantees that Fastify will be compatible and function correctly
|
||||
with N|Solid, aligning with the support and compatibility scope of the N|Solid
|
||||
LTS versions available at the time of the Fastify release.
|
||||
This ensures users of N|Solid can confidently use Fastify.
|
||||
|
||||
A "month" is defined as 30 consecutive days.
|
||||
|
||||
> ## Security Releases and Semver
|
||||
>
|
||||
> As a consequence of providing long-term support for major releases, there are
|
||||
> occasions where we need to release breaking changes as a _minor_ version
|
||||
> release. Such changes will _always_ be noted in the [release
|
||||
> notes](https://github.com/fastify/fastify/releases).
|
||||
>
|
||||
> To avoid automatically receiving breaking security updates it is possible to
|
||||
> use the tilde (`~`) range qualifier. For example, to get patches for the 3.15
|
||||
> release, and avoid automatically updating to the 3.16 release, specify the
|
||||
> dependency as `"fastify": "~3.15.x"`. This will leave your application
|
||||
> vulnerable, so please use with caution.
|
||||
|
||||
### Schedule
|
||||
|
||||
`<a id="lts-schedule"></a>`
|
||||
|
||||
| Version | Release Date | End Of LTS Date | Node.js | Nsolid(Node) |
|
||||
| :------ | :----------- | :-------------- | :----------------- | :------------- |
|
||||
| 1.0.0 | 2018-03-06 | 2019-09-01 | 6, 8, 9, 10, 11 | |
|
||||
| 2.0.0 | 2019-02-25 | 2021-01-31 | 6, 8, 10, 12, 14 | |
|
||||
| 3.0.0 | 2020-07-07 | 2023-06-30 | 10, 12, 14, 16, 18 | v5(18) |
|
||||
| 4.0.0 | 2022-06-08 | TBD | 14, 16, 18, 20 | v5(18), v5(20) |
|
||||
|
||||
### CI tested operating systems
|
||||
|
||||
`<a id="supported-os"></a>`
|
||||
|
||||
Fastify uses GitHub Actions for CI testing, please refer to [GitHub's
|
||||
documentation regarding workflow
|
||||
runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources)
|
||||
for further details on what the latest virtual environment is in relation to the
|
||||
YAML workflow labels below:
|
||||
|
||||
| OS | YAML Workflow Label | Package Manager | Node.js | Nsolid(Node) |
|
||||
| ------- | ------------------- | --------------- | ----------- | ------------- |
|
||||
| Linux | `ubuntu-latest` | npm | 14,16,18,20 | v5(18),v5(20) |
|
||||
| Linux | `ubuntu-latest` | yarn,pnpm | 14,16,18,20 | v5(18),v5(20) |
|
||||
| Windows | `windows-latest` | npm | 14,16,18,20 | v5(18),v5(20) |
|
||||
| MacOS | `macos-latest` | npm | 14,16,18,20 | v5(18),v5(20) |
|
||||
|
||||
Using [yarn](https://yarnpkg.com/) might require passing the `--ignore-engines`
|
||||
flag.
|
||||
|
||||
[semver]: https://semver.org/
|
||||
89
backend/node_modules/fastify/docs/Reference/Lifecycle.md
generated
vendored
Normal file
89
backend/node_modules/fastify/docs/Reference/Lifecycle.md
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Lifecycle
|
||||
<a id="lifecycle"></a>
|
||||
|
||||
Following the schema of the internal lifecycle of Fastify.
|
||||
|
||||
On the right branch of every section there is the next phase of the lifecycle,
|
||||
on the left branch there is the corresponding error code that will be generated
|
||||
if the parent throws an error *(note that all the errors are automatically
|
||||
handled by Fastify)*.
|
||||
|
||||
```
|
||||
Incoming Request
|
||||
│
|
||||
└─▶ Routing
|
||||
│
|
||||
└─▶ Instance Logger
|
||||
│
|
||||
4**/5** ◀─┴─▶ onRequest Hook
|
||||
│
|
||||
4**/5** ◀─┴─▶ preParsing Hook
|
||||
│
|
||||
4**/5** ◀─┴─▶ Parsing
|
||||
│
|
||||
4**/5** ◀─┴─▶ preValidation Hook
|
||||
│
|
||||
400 ◀─┴─▶ Validation
|
||||
│
|
||||
4**/5** ◀─┴─▶ preHandler Hook
|
||||
│
|
||||
4**/5** ◀─┴─▶ User Handler
|
||||
│
|
||||
└─▶ Reply
|
||||
│
|
||||
4**/5** ◀─┴─▶ preSerialization Hook
|
||||
│
|
||||
└─▶ onSend Hook
|
||||
│
|
||||
4**/5** ◀─┴─▶ Outgoing Response
|
||||
│
|
||||
└─▶ onResponse Hook
|
||||
```
|
||||
|
||||
At any point before or during the `User Handler`, `reply.hijack()` can be called
|
||||
to prevent Fastify from:
|
||||
- Running all the following hooks and user handler
|
||||
- Sending the response automatically
|
||||
|
||||
NB (*): If `reply.raw` is used to send a response back to the user, `onResponse`
|
||||
hooks will still be executed
|
||||
|
||||
## Reply Lifecycle
|
||||
<a id="reply-lifecycle"></a>
|
||||
|
||||
Whenever the user handles the request, the result may be:
|
||||
|
||||
- in async handler: it returns a payload
|
||||
- in async handler: it throws an `Error`
|
||||
- in sync handler: it sends a payload
|
||||
- in sync handler: it sends an `Error` instance
|
||||
|
||||
If the reply was hijacked, we skip all the below steps. Otherwise, when it is
|
||||
being submitted, the data flow performed is the following:
|
||||
|
||||
```
|
||||
★ schema validation Error
|
||||
│
|
||||
└─▶ schemaErrorFormatter
|
||||
│
|
||||
reply sent ◀── JSON ─┴─ Error instance
|
||||
│
|
||||
│ ★ throw an Error
|
||||
★ send or return │ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
reply sent ◀── JSON ─┴─ Error instance ──▶ setErrorHandler ◀─────┘
|
||||
│
|
||||
reply sent ◀── JSON ─┴─ Error instance ──▶ onError Hook
|
||||
│
|
||||
└─▶ reply sent
|
||||
```
|
||||
|
||||
Note: `reply sent` means that the JSON payload will be serialized by:
|
||||
|
||||
- the [reply serialized](./Server.md#setreplyserializer) if set
|
||||
- or by the [serializer compiler](./Server.md#setserializercompiler) when a JSON
|
||||
schema has been set for the returning HTTP status code
|
||||
- or by the default `JSON.stringify` function
|
||||
256
backend/node_modules/fastify/docs/Reference/Logging.md
generated
vendored
Normal file
256
backend/node_modules/fastify/docs/Reference/Logging.md
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Logging
|
||||
|
||||
### Enable logging
|
||||
Logging is disabled by default, and you can enable it by passing `{ logger: true
|
||||
}` or `{ logger: { level: 'info' } }` when you create a Fastify instance. Note
|
||||
that if the logger is disabled, it is impossible to enable it at runtime. We use
|
||||
[abstract-logging](https://www.npmjs.com/package/abstract-logging) for this
|
||||
purpose.
|
||||
|
||||
As Fastify is focused on performance, it uses
|
||||
[pino](https://github.com/pinojs/pino) as its logger, with the default log
|
||||
level, when enabled, set to `'info'`.
|
||||
|
||||
Enabling the production JSON logger:
|
||||
|
||||
```js
|
||||
const fastify = require('fastify')({
|
||||
logger: true
|
||||
})
|
||||
```
|
||||
|
||||
Enabling the logger with appropriate configuration for both local development
|
||||
and production and test environment requires a bit more configuration:
|
||||
|
||||
```js
|
||||
const envToLogger = {
|
||||
development: {
|
||||
transport: {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
translateTime: 'HH:MM:ss Z',
|
||||
ignore: 'pid,hostname',
|
||||
},
|
||||
},
|
||||
},
|
||||
production: true,
|
||||
test: false,
|
||||
}
|
||||
const fastify = require('fastify')({
|
||||
logger: envToLogger[environment] ?? true // defaults to true if no entry matches in the map
|
||||
})
|
||||
```
|
||||
⚠️ `pino-pretty` needs to be installed as a dev dependency, it is not included
|
||||
by default for performance reasons.
|
||||
|
||||
### Usage
|
||||
You can use the logger like this in your route handlers:
|
||||
|
||||
```js
|
||||
fastify.get('/', options, function (request, reply) {
|
||||
request.log.info('Some info about the current request')
|
||||
reply.send({ hello: 'world' })
|
||||
})
|
||||
```
|
||||
|
||||
You can trigger new logs outside route handlers by using the Pino instance from
|
||||
the Fastify instance:
|
||||
```js
|
||||
fastify.log.info('Something important happened!');
|
||||
```
|
||||
|
||||
If you want to pass some options to the logger, just pass them to Fastify.
|
||||
You can find all available options in the
|
||||
[Pino documentation](https://github.com/pinojs/pino/blob/master/docs/api.md#options).
|
||||
If you want to specify a file destination, use:
|
||||
|
||||
```js
|
||||
const fastify = require('fastify')({
|
||||
logger: {
|
||||
level: 'info',
|
||||
file: '/path/to/file' // Will use pino.destination()
|
||||
}
|
||||
})
|
||||
|
||||
fastify.get('/', options, function (request, reply) {
|
||||
request.log.info('Some info about the current request')
|
||||
reply.send({ hello: 'world' })
|
||||
})
|
||||
```
|
||||
|
||||
If you want to pass a custom stream to the Pino instance, just add a stream
|
||||
field to the logger object.
|
||||
|
||||
```js
|
||||
const split = require('split2')
|
||||
const stream = split(JSON.parse)
|
||||
|
||||
const fastify = require('fastify')({
|
||||
logger: {
|
||||
level: 'info',
|
||||
stream: stream
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
<a id="logging-request-id"></a>
|
||||
|
||||
By default, Fastify adds an ID to every request for easier tracking. If the
|
||||
"request-id" header is present its value is used, otherwise a new incremental ID
|
||||
is generated. See Fastify Factory
|
||||
[`requestIdHeader`](./Server.md#factory-request-id-header) and Fastify Factory
|
||||
[`genReqId`](./Server.md#genreqid) for customization options.
|
||||
|
||||
The default logger is configured with a set of standard serializers that
|
||||
serialize objects with `req`, `res`, and `err` properties. The object received
|
||||
by `req` is the Fastify [`Request`](./Request.md) object, while the object
|
||||
received by `res` is the Fastify [`Reply`](./Reply.md) object. This behavior
|
||||
can be customized by specifying custom serializers.
|
||||
|
||||
```js
|
||||
const fastify = require('fastify')({
|
||||
logger: {
|
||||
serializers: {
|
||||
req (request) {
|
||||
return { url: request.url }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
For example, the response payload and headers could be logged using the approach
|
||||
below (even if it is *not recommended*):
|
||||
|
||||
```js
|
||||
const fastify = require('fastify')({
|
||||
logger: {
|
||||
transport: {
|
||||
target: 'pino-pretty'
|
||||
},
|
||||
serializers: {
|
||||
res (reply) {
|
||||
// The default
|
||||
return {
|
||||
statusCode: reply.statusCode
|
||||
}
|
||||
},
|
||||
req (request) {
|
||||
return {
|
||||
method: request.method,
|
||||
url: request.url,
|
||||
path: request.routerPath,
|
||||
parameters: request.params,
|
||||
// Including the headers in the log could be in violation
|
||||
// of privacy laws, e.g. GDPR. You should use the "redact" option to
|
||||
// remove sensitive fields. It could also leak authentication data in
|
||||
// the logs.
|
||||
headers: request.headers
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Note**: In certain cases, the [`Reply`](./Reply.md) object passed to the `res`
|
||||
serializer cannot be fully constructed. When writing a custom `res` serializer,
|
||||
it is necessary to check for the existence of any properties on `reply` aside
|
||||
from `statusCode`, which is always present. For example, the existence of
|
||||
`getHeaders` must be verified before it can be called:
|
||||
|
||||
```js
|
||||
const fastify = require('fastify')({
|
||||
logger: {
|
||||
transport: {
|
||||
target: 'pino-pretty'
|
||||
},
|
||||
serializers: {
|
||||
res (reply) {
|
||||
// The default
|
||||
return {
|
||||
statusCode: reply.statusCode
|
||||
headers: typeof reply.getHeaders === 'function'
|
||||
? reply.getHeaders()
|
||||
: {}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Note**: The body cannot be serialized inside a `req` method because the
|
||||
request is serialized when we create the child logger. At that time, the body is
|
||||
not yet parsed.
|
||||
|
||||
See an approach to log `req.body`
|
||||
|
||||
```js
|
||||
app.addHook('preHandler', function (req, reply, done) {
|
||||
if (req.body) {
|
||||
req.log.info({ body: req.body }, 'parsed body')
|
||||
}
|
||||
done()
|
||||
})
|
||||
```
|
||||
|
||||
**Note**: Care should be taken to ensure serializers never throw, as an error
|
||||
thrown from a serializer has the potential to cause the Node process to exit.
|
||||
See the [Pino documentation](https://getpino.io/#/docs/api?id=opt-serializers)
|
||||
on serializers for more information.
|
||||
|
||||
*Any logger other than Pino will ignore this option.*
|
||||
|
||||
You can also supply your own logger instance. Instead of passing configuration
|
||||
options, pass the instance. The logger you supply must conform to the Pino
|
||||
interface; that is, it must have the following methods: `info`, `error`,
|
||||
`debug`, `fatal`, `warn`, `trace`, `silent`, `child` and a string property `level`.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
const log = require('pino')({ level: 'info' })
|
||||
const fastify = require('fastify')({ logger: log })
|
||||
|
||||
log.info('does not have request information')
|
||||
|
||||
fastify.get('/', function (request, reply) {
|
||||
request.log.info('includes request information, but is the same logger instance as `log`')
|
||||
reply.send({ hello: 'world' })
|
||||
})
|
||||
```
|
||||
|
||||
*The logger instance for the current request is available in every part of the
|
||||
[lifecycle](./Lifecycle.md).*
|
||||
|
||||
## Log Redaction
|
||||
|
||||
[Pino](https://getpino.io) supports low-overhead log redaction for obscuring
|
||||
values of specific properties in recorded logs. As an example, we might want to
|
||||
log all the HTTP headers minus the `Authorization` header for security concerns:
|
||||
|
||||
```js
|
||||
const fastify = Fastify({
|
||||
logger: {
|
||||
stream: stream,
|
||||
redact: ['req.headers.authorization'],
|
||||
level: 'info',
|
||||
serializers: {
|
||||
req (request) {
|
||||
return {
|
||||
method: request.method,
|
||||
url: request.url,
|
||||
headers: request.headers,
|
||||
hostname: request.hostname,
|
||||
remoteAddress: request.ip,
|
||||
remotePort: request.socket.remotePort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
See https://getpino.io/#/docs/redaction for more details.
|
||||
78
backend/node_modules/fastify/docs/Reference/Middleware.md
generated
vendored
Normal file
78
backend/node_modules/fastify/docs/Reference/Middleware.md
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Middleware
|
||||
|
||||
Starting with Fastify v3.0.0, middleware is not supported out of the box and
|
||||
requires an external plugin such as
|
||||
[`@fastify/express`](https://github.com/fastify/fastify-express) or
|
||||
[`@fastify/middie`](https://github.com/fastify/middie).
|
||||
|
||||
|
||||
An example of registering the
|
||||
[`@fastify/express`](https://github.com/fastify/fastify-express) plugin to `use`
|
||||
Express middleware:
|
||||
|
||||
```js
|
||||
await fastify.register(require('@fastify/express'))
|
||||
fastify.use(require('cors')())
|
||||
fastify.use(require('dns-prefetch-control')())
|
||||
fastify.use(require('frameguard')())
|
||||
fastify.use(require('hsts')())
|
||||
fastify.use(require('ienoopen')())
|
||||
fastify.use(require('x-xss-protection')())
|
||||
```
|
||||
|
||||
You can also use [`@fastify/middie`](https://github.com/fastify/middie), which provides
|
||||
support for simple Express-style middleware but with improved performance:
|
||||
|
||||
```js
|
||||
await fastify.register(require('@fastify/middie'))
|
||||
fastify.use(require('cors')())
|
||||
```
|
||||
|
||||
Remember that middleware can be encapsulated; this means that you can decide
|
||||
where your middleware should run by using `register` as explained in the
|
||||
[plugins guide](../Guides/Plugins-Guide.md).
|
||||
|
||||
Fastify middleware does not expose the `send` method or other methods specific to
|
||||
the Fastify [Reply](./Reply.md#reply) instance. This is because Fastify wraps
|
||||
the incoming `req` and `res` Node instances using the
|
||||
[Request](./Request.md#request) and [Reply](./Reply.md#reply) objects
|
||||
internally, but this is done after the middleware phase. If you need to create
|
||||
middleware, you have to use the Node `req` and `res` instances. Otherwise, you
|
||||
can use the `preHandler` hook that already has the
|
||||
[Request](./Request.md#request) and [Reply](./Reply.md#reply) Fastify instances.
|
||||
For more information, see [Hooks](./Hooks.md#hooks).
|
||||
|
||||
#### Restrict middleware execution to certain paths
|
||||
<a id="restrict-usage"></a>
|
||||
|
||||
If you need to only run middleware under certain paths, just pass the path as
|
||||
the first parameter to `use` and you are done!
|
||||
|
||||
*Note that this does not support routes with parameters, (e.g.
|
||||
`/user/:id/comments`) and wildcards are not supported in multiple paths.*
|
||||
|
||||
```js
|
||||
const path = require('node:path')
|
||||
const serveStatic = require('serve-static')
|
||||
|
||||
// Single path
|
||||
fastify.use('/css', serveStatic(path.join(__dirname, '/assets')))
|
||||
|
||||
// Wildcard path
|
||||
fastify.use('/css/(.*)', serveStatic(path.join(__dirname, '/assets')))
|
||||
|
||||
// Multiple paths
|
||||
fastify.use(['/css', '/js'], serveStatic(path.join(__dirname, '/assets')))
|
||||
```
|
||||
|
||||
### Alternatives
|
||||
|
||||
Fastify offers some alternatives to the most commonly used middleware, such as
|
||||
[`@fastify/helmet`](https://github.com/fastify/fastify-helmet) in case of
|
||||
[`helmet`](https://github.com/helmetjs/helmet),
|
||||
[`@fastify/cors`](https://github.com/fastify/fastify-cors) for
|
||||
[`cors`](https://github.com/expressjs/cors), and
|
||||
[`@fastify/static`](https://github.com/fastify/fastify-static) for
|
||||
[`serve-static`](https://github.com/expressjs/serve-static).
|
||||
252
backend/node_modules/fastify/docs/Reference/Plugins.md
generated
vendored
Normal file
252
backend/node_modules/fastify/docs/Reference/Plugins.md
generated
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Plugins
|
||||
Fastify allows the user to extend its functionalities with plugins. A plugin can
|
||||
be a set of routes, a server [decorator](./Decorators.md), or whatever. The API
|
||||
that you will need to use one or more plugins, is `register`.
|
||||
|
||||
By default, `register` creates a *new scope*, this means that if you make some
|
||||
changes to the Fastify instance (via `decorate`), this change will not be
|
||||
reflected by the current context ancestors, but only by its descendants. This
|
||||
feature allows us to achieve plugin *encapsulation* and *inheritance*, in this
|
||||
way we create a *directed acyclic graph* (DAG) and we will not have issues
|
||||
caused by cross dependencies.
|
||||
|
||||
You may have already seen in the [Getting
|
||||
Started](../Guides/Getting-Started.md#your-first-plugin) guide how easy it is
|
||||
to use this API:
|
||||
```
|
||||
fastify.register(plugin, [options])
|
||||
```
|
||||
|
||||
### Plugin Options
|
||||
<a id="plugin-options"></a>
|
||||
|
||||
The optional `options` parameter for `fastify.register` supports a predefined
|
||||
set of options that Fastify itself will use, except when the plugin has been
|
||||
wrapped with [fastify-plugin](https://github.com/fastify/fastify-plugin). This
|
||||
options object will also be passed to the plugin upon invocation, regardless of
|
||||
whether or not the plugin has been wrapped. The currently supported list of
|
||||
Fastify specific options is:
|
||||
|
||||
+ [`logLevel`](./Routes.md#custom-log-level)
|
||||
+ [`logSerializers`](./Routes.md#custom-log-serializer)
|
||||
+ [`prefix`](#route-prefixing-option)
|
||||
|
||||
**Note: Those options will be ignored when used with fastify-plugin**
|
||||
|
||||
It is possible that Fastify will directly support other options in the future.
|
||||
Thus, to avoid collisions, a plugin should consider namespacing its options. For
|
||||
example, a plugin `foo` might be registered like so:
|
||||
|
||||
```js
|
||||
fastify.register(require('fastify-foo'), {
|
||||
prefix: '/foo',
|
||||
foo: {
|
||||
fooOption1: 'value',
|
||||
fooOption2: 'value'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
If collisions are not a concern, the plugin may simply accept the options object
|
||||
as-is:
|
||||
|
||||
```js
|
||||
fastify.register(require('fastify-foo'), {
|
||||
prefix: '/foo',
|
||||
fooOption1: 'value',
|
||||
fooOption2: 'value'
|
||||
})
|
||||
```
|
||||
|
||||
The `options` parameter can also be a `Function` that will be evaluated at the
|
||||
time the plugin is registered while giving access to the Fastify instance via
|
||||
the first positional argument:
|
||||
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
fastify.register(fp((fastify, opts, done) => {
|
||||
fastify.decorate('foo_bar', { hello: 'world' })
|
||||
|
||||
done()
|
||||
}))
|
||||
|
||||
// The opts argument of fastify-foo will be { hello: 'world' }
|
||||
fastify.register(require('fastify-foo'), parent => parent.foo_bar)
|
||||
```
|
||||
|
||||
The Fastify instance passed on to the function is the latest state of the
|
||||
**external Fastify instance** the plugin was declared on, allowing access to
|
||||
variables injected via [`decorate`](./Decorators.md) by preceding plugins
|
||||
according to the **order of registration**. This is useful in case a plugin
|
||||
depends on changes made to the Fastify instance by a preceding plugin i.e.
|
||||
utilizing an existing database connection to wrap around it.
|
||||
|
||||
Keep in mind that the Fastify instance passed on to the function is the same as
|
||||
the one that will be passed into the plugin, a copy of the external Fastify
|
||||
instance rather than a reference. Any usage of the instance will behave the same
|
||||
as it would if called within the plugins function i.e. if `decorate` is called,
|
||||
the decorated variables will be available within the plugins function unless it
|
||||
was wrapped with [`fastify-plugin`](https://github.com/fastify/fastify-plugin).
|
||||
|
||||
#### Route Prefixing option
|
||||
<a id="route-prefixing-option"></a>
|
||||
|
||||
If you pass an option with the key `prefix` with a `string` value, Fastify will
|
||||
use it to prefix all the routes inside the register, for more info check
|
||||
[here](./Routes.md#route-prefixing).
|
||||
|
||||
Be aware that if you wrap your routes with
|
||||
[`fastify-plugin`](https://github.com/fastify/fastify-plugin), this option will
|
||||
not work (there is a [workaround](./Routes.md#fastify-plugin) available).
|
||||
|
||||
#### Error handling
|
||||
<a id="error-handling"></a>
|
||||
|
||||
The error handling is done by
|
||||
[avvio](https://github.com/mcollina/avvio#error-handling).
|
||||
|
||||
As a general rule, it is highly recommended that you handle your errors in the
|
||||
next `after` or `ready` block, otherwise you will get them inside the `listen`
|
||||
callback.
|
||||
|
||||
```js
|
||||
fastify.register(require('my-plugin'))
|
||||
|
||||
// `after` will be executed once
|
||||
// the previous declared `register` has finished
|
||||
fastify.after(err => console.log(err))
|
||||
|
||||
// `ready` will be executed once all the registers declared
|
||||
// have finished their execution
|
||||
fastify.ready(err => console.log(err))
|
||||
|
||||
// `listen` is a special ready,
|
||||
// so it behaves in the same way
|
||||
fastify.listen({ port: 3000 }, (err, address) => {
|
||||
if (err) console.log(err)
|
||||
})
|
||||
```
|
||||
|
||||
### async/await
|
||||
<a id="async-await"></a>
|
||||
|
||||
*async/await* is supported by `after`, `ready`, and `listen`, as well as
|
||||
`fastify` being a Thenable.
|
||||
|
||||
```js
|
||||
await fastify.register(require('my-plugin'))
|
||||
|
||||
await fastify.after()
|
||||
|
||||
await fastify.ready()
|
||||
|
||||
await fastify.listen({ port: 3000 })
|
||||
```
|
||||
*Note: Using `await` when registering a plugin loads the plugin
|
||||
and the underlying dependency tree, "finalizing" the encapsulation process.
|
||||
Any mutations to the plugin after it and its dependencies have been
|
||||
loaded will not be reflected in the parent instance.*
|
||||
|
||||
#### ESM support
|
||||
<a id="esm-support"></a>
|
||||
|
||||
ESM is supported as well from [Node.js
|
||||
`v13.3.0`](https://nodejs.org/api/esm.html) and above!
|
||||
|
||||
```js
|
||||
// main.mjs
|
||||
import Fastify from 'fastify'
|
||||
const fastify = Fastify()
|
||||
|
||||
fastify.register(import('./plugin.mjs'))
|
||||
|
||||
fastify.listen({ port: 3000 }, console.log)
|
||||
|
||||
|
||||
// plugin.mjs
|
||||
async function plugin (fastify, opts) {
|
||||
fastify.get('/', async (req, reply) => {
|
||||
return { hello: 'world' }
|
||||
})
|
||||
}
|
||||
|
||||
export default plugin
|
||||
```
|
||||
|
||||
### Create a plugin
|
||||
<a id="create-plugin"></a>
|
||||
|
||||
Creating a plugin is very easy, you just need to create a function that takes
|
||||
three parameters, the `fastify` instance, an `options` object, and the `done`
|
||||
callback.
|
||||
|
||||
Example:
|
||||
```js
|
||||
module.exports = function (fastify, opts, done) {
|
||||
fastify.decorate('utility', function () {})
|
||||
|
||||
fastify.get('/', handler)
|
||||
|
||||
done()
|
||||
}
|
||||
```
|
||||
You can also use `register` inside another `register`:
|
||||
```js
|
||||
module.exports = function (fastify, opts, done) {
|
||||
fastify.decorate('utility', function () {})
|
||||
|
||||
fastify.get('/', handler)
|
||||
|
||||
fastify.register(require('./other-plugin'))
|
||||
|
||||
done()
|
||||
}
|
||||
```
|
||||
Sometimes, you will need to know when the server is about to close, for example,
|
||||
because you must close a connection to a database. To know when this is going to
|
||||
happen, you can use the [`'onClose'`](./Hooks.md#on-close) hook.
|
||||
|
||||
Do not forget that `register` will always create a new Fastify scope, if you do
|
||||
not need that, read the following section.
|
||||
|
||||
### Handle the scope
|
||||
<a id="handle-scope"></a>
|
||||
|
||||
If you are using `register` only for extending the functionality of the server
|
||||
with [`decorate`](./Decorators.md), it is your responsibility to tell Fastify
|
||||
not to create a new scope. Otherwise, your changes will not be accessible by the
|
||||
user in the upper scope.
|
||||
|
||||
You have two ways to tell Fastify to avoid the creation of a new context:
|
||||
- Use the [`fastify-plugin`](https://github.com/fastify/fastify-plugin) module
|
||||
- Use the `'skip-override'` hidden property
|
||||
|
||||
We recommend using the `fastify-plugin` module, because it solves this problem
|
||||
for you, and you can pass a version range of Fastify as a parameter that your
|
||||
plugin will support.
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
|
||||
module.exports = fp(function (fastify, opts, done) {
|
||||
fastify.decorate('utility', function () {})
|
||||
done()
|
||||
}, '0.x')
|
||||
```
|
||||
Check the [`fastify-plugin`](https://github.com/fastify/fastify-plugin)
|
||||
documentation to learn more about how to use this module.
|
||||
|
||||
If you do not use the `fastify-plugin` module, you can use the `'skip-override'`
|
||||
hidden property, but we do not recommend it. If in the future the Fastify API
|
||||
changes it will be your responsibility to update the module, while if you use
|
||||
`fastify-plugin`, you can be sure about backward compatibility.
|
||||
```js
|
||||
function yourPlugin (fastify, opts, done) {
|
||||
fastify.decorate('utility', function () {})
|
||||
done()
|
||||
}
|
||||
yourPlugin[Symbol.for('skip-override')] = true
|
||||
module.exports = yourPlugin
|
||||
```
|
||||
78
backend/node_modules/fastify/docs/Reference/Principles.md
generated
vendored
Normal file
78
backend/node_modules/fastify/docs/Reference/Principles.md
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
# Technical Principles
|
||||
|
||||
Every decision in the Fastify framework and its official plugins is guided by
|
||||
the following technical principles:
|
||||
|
||||
1. “Zero” overhead in production
|
||||
2. “Good” developer experience
|
||||
3. Works great for small & big projects alike
|
||||
4. Easy to migrate to microservices (or even serverless) and back
|
||||
5. Security & data validation
|
||||
6. If something could be a plugin, it likely should be
|
||||
7. Easily testable
|
||||
8. Do not monkeypatch core
|
||||
9. Semantic versioning & Long Term Support
|
||||
10. Specification adherence
|
||||
|
||||
## "Zero" Overhead in Production
|
||||
|
||||
Fastify aims to implement its features by adding as minimal overhead to your
|
||||
application as possible.
|
||||
This is usually delivered by implementing fast algorithms and data structures,
|
||||
as well as JavaScript-specific features.
|
||||
|
||||
Given that JavaScript does not offer zero-overhead data structures, this principle
|
||||
is at odds with providing a great developer experience and providing more features,
|
||||
as usually those cost some overhead.
|
||||
|
||||
## "Good" Developer Experience
|
||||
|
||||
Fastify aims to provide the best developer experience at the performance point
|
||||
it is operating.
|
||||
It provides a great out-of-the-box experience that is flexible enough to be
|
||||
adapted to a variety of situations.
|
||||
|
||||
As an example, this means that binary addons are forbidden because most JavaScript
|
||||
developers would not
|
||||
have access to a compiler.
|
||||
|
||||
## Works great for small and big projects alike
|
||||
|
||||
We recognize that most applications start small and become more complex over time.
|
||||
Fastify aims to grow with
|
||||
the complexity of your application, providing advanced features to structure
|
||||
your codebase.
|
||||
|
||||
## Easy to migrate to microservices (or even serverless) and back
|
||||
|
||||
How you deploy your routes should not matter. The framework should "just work".
|
||||
|
||||
## Security and Data Validation
|
||||
|
||||
Your web framework is the first point of contact with untrusted data, and it
|
||||
needs to act as the first line of defense for your system.
|
||||
|
||||
## If something could be a plugin, it likely should
|
||||
|
||||
We recognize that there are an infinite amount of use cases for an HTTP framework
|
||||
for Node.js. Catering to them in a single module would make the codebase unmaintainable.
|
||||
Therefore we provide hooks and options to allow you to customize the framework
|
||||
as you please.
|
||||
|
||||
## Easily testable
|
||||
|
||||
Testing Fastify applications should be a first-class concern.
|
||||
|
||||
## Do not monkeypatch core
|
||||
|
||||
Monkeypatch Node.js APIs or installing globals that alter the behavior of the
|
||||
runtime makes building modular applications harder, and limit the use cases of Fastify.
|
||||
Other frameworks do this and we do not.
|
||||
|
||||
## Semantic Versioning and Long Term Support
|
||||
|
||||
We provide a clear Long Term Support strategy so developers can know when to upgrade.
|
||||
|
||||
## Specification adherence
|
||||
|
||||
In doubt, we chose the strict behavior as defined by the relevant Specifications.
|
||||
978
backend/node_modules/fastify/docs/Reference/Reply.md
generated
vendored
Normal file
978
backend/node_modules/fastify/docs/Reference/Reply.md
generated
vendored
Normal file
@@ -0,0 +1,978 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Reply
|
||||
- [Reply](#reply)
|
||||
- [Introduction](#introduction)
|
||||
- [.code(statusCode)](#codestatuscode)
|
||||
- [.elapsedTime](#elapsedtime)
|
||||
- [.statusCode](#statuscode)
|
||||
- [.server](#server)
|
||||
- [.header(key, value)](#headerkey-value)
|
||||
- [.headers(object)](#headersobject)
|
||||
- [.getHeader(key)](#getheaderkey)
|
||||
- [.getHeaders()](#getheaders)
|
||||
- [set-cookie](#set-cookie)
|
||||
- [.removeHeader(key)](#removeheaderkey)
|
||||
- [.hasHeader(key)](#hasheaderkey)
|
||||
- [.trailer(key, function)](#trailerkey-function)
|
||||
- [.hasTrailer(key)](#hastrailerkey)
|
||||
- [.removeTrailer(key)](#removetrailerkey)
|
||||
- [.redirect(dest, [code ,])](#redirectdest--code)
|
||||
- [.callNotFound()](#callnotfound)
|
||||
- [.getResponseTime()](#getresponsetime)
|
||||
- [.type(contentType)](#typecontenttype)
|
||||
- [.getSerializationFunction(schema | httpStatus, [contentType])](#getserializationfunctionschema--httpstatus)
|
||||
- [.compileSerializationSchema(schema, [httpStatus], [contentType])](#compileserializationschemaschema-httpstatus)
|
||||
- [.serializeInput(data, [schema | httpStatus], [httpStatus], [contentType])](#serializeinputdata-schema--httpstatus-httpstatus)
|
||||
- [.serializer(func)](#serializerfunc)
|
||||
- [.raw](#raw)
|
||||
- [.sent](#sent)
|
||||
- [.hijack()](#hijack)
|
||||
- [.send(data)](#senddata)
|
||||
- [Objects](#objects)
|
||||
- [Strings](#strings)
|
||||
- [Streams](#streams)
|
||||
- [Buffers](#buffers)
|
||||
- [ReadableStream](#send-readablestream)
|
||||
- [Response](#send-response)
|
||||
- [Errors](#errors)
|
||||
- [Type of the final payload](#type-of-the-final-payload)
|
||||
- [Async-Await and Promises](#async-await-and-promises)
|
||||
- [.then(fulfilled, rejected)](#thenfulfilled-rejected)
|
||||
|
||||
### Introduction
|
||||
<a id="introduction"></a>
|
||||
|
||||
The second parameter of the handler function is `Reply`. Reply is a core Fastify
|
||||
object that exposes the following functions and properties:
|
||||
|
||||
- `.code(statusCode)` - Sets the status code.
|
||||
- `.status(statusCode)` - An alias for `.code(statusCode)`.
|
||||
- `.statusCode` - Read and set the HTTP status code.
|
||||
- `.elapsedTime` - Returns the amount of time passed
|
||||
since the request was received by Fastify.
|
||||
- `.server` - A reference to the fastify instance object.
|
||||
- `.header(name, value)` - Sets a response header.
|
||||
- `.headers(object)` - Sets all the keys of the object as response headers.
|
||||
- `.getHeader(name)` - Retrieve value of already set header.
|
||||
- `.getHeaders()` - Gets a shallow copy of all current response headers.
|
||||
- `.removeHeader(key)` - Remove the value of a previously set header.
|
||||
- `.hasHeader(name)` - Determine if a header has been set.
|
||||
- `.trailer(key, function)` - Sets a response trailer.
|
||||
- `.hasTrailer(key)` - Determine if a trailer has been set.
|
||||
- `.removeTrailer(key)` - Remove the value of a previously set trailer.
|
||||
- `.type(value)` - Sets the header `Content-Type`.
|
||||
- `.redirect(dest, [code,])` - Redirect to the specified URL, the status code is
|
||||
optional (defaults to `302`).
|
||||
- `.callNotFound()` - Invokes the custom not found handler.
|
||||
- `.serialize(payload)` - Serializes the specified payload using the default
|
||||
JSON serializer or using the custom serializer (if one is set) and returns the
|
||||
serialized payload.
|
||||
- `.getSerializationFunction(schema | httpStatus, [contentType])` - Returns the serialization
|
||||
function for the specified schema or http status, if any of either are set.
|
||||
- `.compileSerializationSchema(schema, [httpStatus], [contentType])` - Compiles
|
||||
the specified schema and returns a serialization function using the default
|
||||
(or customized) `SerializerCompiler`. The optional `httpStatus` is forwarded
|
||||
to the `SerializerCompiler` if provided, default to `undefined`.
|
||||
- `.serializeInput(data, schema, [,httpStatus], [contentType])` - Serializes
|
||||
the specified data using the specified schema and returns the serialized payload.
|
||||
If the optional `httpStatus`, and `contentType` are provided, the function
|
||||
will use the serializer function given for that specific content type and
|
||||
HTTP Status Code. Default to `undefined`.
|
||||
- `.serializer(function)` - Sets a custom serializer for the payload.
|
||||
- `.send(payload)` - Sends the payload to the user, could be a plain text, a
|
||||
buffer, JSON, stream, or an Error object.
|
||||
- `.sent` - A boolean value that you can use if you need to know if `send` has
|
||||
already been called.
|
||||
- `.hijack()` - interrupt the normal request lifecycle.
|
||||
- `.raw` - The
|
||||
[`http.ServerResponse`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_class_http_serverresponse)
|
||||
from Node core.
|
||||
- `.log` - The logger instance of the incoming request.
|
||||
- `.request` - The incoming request.
|
||||
- `.getResponseTime()` - Deprecated, returns the amount of time passed
|
||||
since the request was received by Fastify.
|
||||
- `.context` - Deprecated, access the [Request's context](./Request.md) property.
|
||||
|
||||
```js
|
||||
fastify.get('/', options, function (request, reply) {
|
||||
// Your code
|
||||
reply
|
||||
.code(200)
|
||||
.header('Content-Type', 'application/json; charset=utf-8')
|
||||
.send({ hello: 'world' })
|
||||
})
|
||||
```
|
||||
|
||||
Additionally, `Reply` provides access to the context of the request:
|
||||
|
||||
```js
|
||||
fastify.get('/', {config: {foo: 'bar'}}, function (request, reply) {
|
||||
reply.send('handler config.foo = ' + reply.context.config.foo)
|
||||
})
|
||||
```
|
||||
|
||||
### .code(statusCode)
|
||||
<a id="code"></a>
|
||||
|
||||
If not set via `reply.code`, the resulting `statusCode` will be `200`.
|
||||
|
||||
### .elapsedTime
|
||||
<a id="elapsedTime"></a>
|
||||
|
||||
Invokes the custom response time getter to calculate the amount of time passed
|
||||
since the request was received by Fastify.
|
||||
|
||||
Note that unless this function is called in the [`onResponse`
|
||||
hook](./Hooks.md#onresponse) it will always return `0`.
|
||||
|
||||
```js
|
||||
const milliseconds = reply.elapsedTime
|
||||
```
|
||||
|
||||
### .statusCode
|
||||
<a id="statusCode"></a>
|
||||
|
||||
This property reads and sets the HTTP status code. It is an alias for
|
||||
`reply.code()` when used as a setter.
|
||||
```js
|
||||
if (reply.statusCode >= 299) {
|
||||
reply.statusCode = 500
|
||||
}
|
||||
```
|
||||
|
||||
### .server
|
||||
<a id="server"></a>
|
||||
|
||||
The Fastify server instance, scoped to the current [encapsulation
|
||||
context](./Encapsulation.md).
|
||||
|
||||
```js
|
||||
fastify.decorate('util', function util () {
|
||||
return 'foo'
|
||||
})
|
||||
|
||||
fastify.get('/', async function (req, rep) {
|
||||
return rep.server.util() // foo
|
||||
})
|
||||
```
|
||||
|
||||
### .header(key, value)
|
||||
<a id="header"></a>
|
||||
|
||||
Sets a response header. If the value is omitted or undefined, it is coerced to
|
||||
`''`.
|
||||
|
||||
> Note: the header's value must be properly encoded using
|
||||
> [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
|
||||
> or similar modules such as
|
||||
> [`encodeurl`](https://www.npmjs.com/package/encodeurl). Invalid characters
|
||||
> will result in a 500 `TypeError` response.
|
||||
|
||||
For more information, see
|
||||
[`http.ServerResponse#setHeader`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_response_setheader_name_value).
|
||||
|
||||
- ### set-cookie
|
||||
<a id="set-cookie"></a>
|
||||
|
||||
- When sending different values as a cookie with `set-cookie` as the key,
|
||||
every value will be sent as a cookie instead of replacing the previous
|
||||
value.
|
||||
|
||||
```js
|
||||
reply.header('set-cookie', 'foo');
|
||||
reply.header('set-cookie', 'bar');
|
||||
```
|
||||
- The browser will only consider the latest reference of a key for the
|
||||
`set-cookie` header. This is done to avoid parsing the `set-cookie` header
|
||||
when added to a reply and speeds up the serialization of the reply.
|
||||
|
||||
- To reset the `set-cookie` header, you need to make an explicit call to
|
||||
`reply.removeHeader('set-cookie')`, read more about `.removeHeader(key)`
|
||||
[here](#removeheaderkey).
|
||||
|
||||
|
||||
|
||||
### .headers(object)
|
||||
<a id="headers"></a>
|
||||
|
||||
Sets all the keys of the object as response headers.
|
||||
[`.header`](#headerkey-value) will be called under the hood.
|
||||
```js
|
||||
reply.headers({
|
||||
'x-foo': 'foo',
|
||||
'x-bar': 'bar'
|
||||
})
|
||||
```
|
||||
|
||||
### .getHeader(key)
|
||||
<a id="getHeader"></a>
|
||||
|
||||
Retrieves the value of a previously set header.
|
||||
```js
|
||||
reply.header('x-foo', 'foo') // setHeader: key, value
|
||||
reply.getHeader('x-foo') // 'foo'
|
||||
```
|
||||
|
||||
### .getHeaders()
|
||||
<a id="getHeaders"></a>
|
||||
|
||||
Gets a shallow copy of all current response headers, including those set via the
|
||||
raw `http.ServerResponse`. Note that headers set via Fastify take precedence
|
||||
over those set via `http.ServerResponse`.
|
||||
|
||||
```js
|
||||
reply.header('x-foo', 'foo')
|
||||
reply.header('x-bar', 'bar')
|
||||
reply.raw.setHeader('x-foo', 'foo2')
|
||||
reply.getHeaders() // { 'x-foo': 'foo', 'x-bar': 'bar' }
|
||||
```
|
||||
|
||||
### .removeHeader(key)
|
||||
<a id="getHeader"></a>
|
||||
|
||||
Remove the value of a previously set header.
|
||||
```js
|
||||
reply.header('x-foo', 'foo')
|
||||
reply.removeHeader('x-foo')
|
||||
reply.getHeader('x-foo') // undefined
|
||||
```
|
||||
|
||||
### .hasHeader(key)
|
||||
<a id="hasHeader"></a>
|
||||
|
||||
Returns a boolean indicating if the specified header has been set.
|
||||
|
||||
### .trailer(key, function)
|
||||
<a id="trailer"></a>
|
||||
|
||||
Sets a response trailer. Trailer is usually used when you need a header that
|
||||
requires heavy resources to be sent after the `data`, for example,
|
||||
`Server-Timing` and `Etag`. It can ensure the client receives the response data
|
||||
as soon as possible.
|
||||
|
||||
*Note: The header `Transfer-Encoding: chunked` will be added once you use the
|
||||
trailer. It is a hard requirement for using trailer in Node.js.*
|
||||
|
||||
*Note: Any error passed to `done` callback will be ignored. If you interested
|
||||
in the error, you can turn on `debug` level logging.*
|
||||
|
||||
```js
|
||||
reply.trailer('server-timing', function() {
|
||||
return 'db;dur=53, app;dur=47.2'
|
||||
})
|
||||
|
||||
const { createHash } = require('node:crypto')
|
||||
// trailer function also receive two argument
|
||||
// @param {object} reply fastify reply
|
||||
// @param {string|Buffer|null} payload payload that already sent, note that it will be null when stream is sent
|
||||
// @param {function} done callback to set trailer value
|
||||
reply.trailer('content-md5', function(reply, payload, done) {
|
||||
const hash = createHash('md5')
|
||||
hash.update(payload)
|
||||
done(null, hash.disgest('hex'))
|
||||
})
|
||||
|
||||
// when you prefer async-await
|
||||
reply.trailer('content-md5', async function(reply, payload) {
|
||||
const hash = createHash('md5')
|
||||
hash.update(payload)
|
||||
return hash.disgest('hex')
|
||||
})
|
||||
```
|
||||
|
||||
### .hasTrailer(key)
|
||||
<a id="hasTrailer"></a>
|
||||
|
||||
Returns a boolean indicating if the specified trailer has been set.
|
||||
|
||||
### .removeTrailer(key)
|
||||
<a id="removeTrailer"></a>
|
||||
|
||||
Remove the value of a previously set trailer.
|
||||
```js
|
||||
reply.trailer('server-timing', function() {
|
||||
return 'db;dur=53, app;dur=47.2'
|
||||
})
|
||||
reply.removeTrailer('server-timing')
|
||||
reply.getTrailer('server-timing') // undefined
|
||||
```
|
||||
|
||||
|
||||
### .redirect(dest, [code ,])
|
||||
<a id="redirect"></a>
|
||||
|
||||
Redirects a request to the specified URL, the status code is optional, default
|
||||
to `302` (if status code is not already set by calling `code`).
|
||||
|
||||
> Note: the input URL must be properly encoded using
|
||||
> [`encodeURI`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
|
||||
> or similar modules such as
|
||||
> [`encodeurl`](https://www.npmjs.com/package/encodeurl). Invalid URLs will
|
||||
> result in a 500 `TypeError` response.
|
||||
|
||||
Example (no `reply.code()` call) sets status code to `302` and redirects to
|
||||
`/home`
|
||||
```js
|
||||
reply.redirect('/home')
|
||||
```
|
||||
|
||||
Example (no `reply.code()` call) sets status code to `303` and redirects to
|
||||
`/home`
|
||||
```js
|
||||
reply.redirect('/home', 303)
|
||||
```
|
||||
|
||||
Example (`reply.code()` call) sets status code to `303` and redirects to `/home`
|
||||
```js
|
||||
reply.code(303).redirect('/home')
|
||||
```
|
||||
|
||||
Example (`reply.code()` call) sets status code to `302` and redirects to `/home`
|
||||
```js
|
||||
reply.code(303).redirect('/home', 302)
|
||||
```
|
||||
|
||||
### .callNotFound()
|
||||
<a id="call-not-found"></a>
|
||||
|
||||
Invokes the custom not found handler. Note that it will only call `preHandler`
|
||||
hook specified in [`setNotFoundHandler`](./Server.md#set-not-found-handler).
|
||||
|
||||
```js
|
||||
reply.callNotFound()
|
||||
```
|
||||
|
||||
### .getResponseTime()
|
||||
<a id="getResponseTime"></a>
|
||||
|
||||
Invokes the custom response time getter to calculate the amount of time passed
|
||||
since the request was received by Fastify.
|
||||
|
||||
Note that unless this function is called in the [`onResponse`
|
||||
hook](./Hooks.md#onresponse) it will always return `0`.
|
||||
|
||||
```js
|
||||
const milliseconds = reply.getResponseTime()
|
||||
```
|
||||
|
||||
*Note: This method is deprecated and will be removed in `fastify@5`.
|
||||
Use the [.elapsedTime](#elapsedtime) property instead.*
|
||||
|
||||
### .type(contentType)
|
||||
<a id="type"></a>
|
||||
|
||||
Sets the content type for the response. This is a shortcut for
|
||||
`reply.header('Content-Type', 'the/type')`.
|
||||
|
||||
```js
|
||||
reply.type('text/html')
|
||||
```
|
||||
If the `Content-Type` has a JSON subtype, and the charset parameter is not set,
|
||||
`utf-8` will be used as the charset by default.
|
||||
|
||||
### .getSerializationFunction(schema | httpStatus, [contentType])
|
||||
<a id="getserializationfunction"></a>
|
||||
|
||||
By calling this function using a provided `schema` or `httpStatus`,
|
||||
and the optional `contentType`, it will return a `serialzation` function
|
||||
that can be used to serialize diverse inputs. It returns `undefined` if no
|
||||
serialization function was found using either of the provided inputs.
|
||||
|
||||
This heavily depends of the `schema#responses` attached to the route, or
|
||||
the serialization functions compiled by using `compileSerializationSchema`.
|
||||
|
||||
```js
|
||||
const serialize = reply
|
||||
.getSerializationFunction({
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
})
|
||||
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
|
||||
|
||||
// or
|
||||
|
||||
const serialize = reply
|
||||
.getSerializationFunction(200)
|
||||
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
|
||||
|
||||
// or
|
||||
|
||||
const serialize = reply
|
||||
.getSerializationFunction(200, 'application/json')
|
||||
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
|
||||
```
|
||||
|
||||
See [.compileSerializationSchema(schema, [httpStatus], [contentType])](#compileserializationschema)
|
||||
for more information on how to compile serialization schemas.
|
||||
|
||||
### .compileSerializationSchema(schema, [httpStatus], [contentType])
|
||||
<a id="compileserializationschema"></a>
|
||||
|
||||
This function will compile a serialization schema and
|
||||
return a function that can be used to serialize data.
|
||||
The function returned (a.k.a. _serialization function_) returned is compiled
|
||||
by using the provided `SerializerCompiler`. Also this is cached by using
|
||||
a `WeakMap` for reducing compilation calls.
|
||||
|
||||
The optional parameters `httpStatus` and `contentType`, if provided,
|
||||
are forwarded directly to the `SerializerCompiler`, so it can be used
|
||||
to compile the serialization function if a custom `SerializerCompiler` is used.
|
||||
|
||||
This heavily depends of the `schema#responses` attached to the route, or
|
||||
the serialization functions compiled by using `compileSerializationSchema`.
|
||||
|
||||
```js
|
||||
const serialize = reply
|
||||
.compileSerializationSchema({
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
})
|
||||
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
|
||||
|
||||
// or
|
||||
|
||||
const serialize = reply
|
||||
.compileSerializationSchema({
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}, 200)
|
||||
serialize({ foo: 'bar' }) // '{"foo":"bar"}'
|
||||
|
||||
// or
|
||||
|
||||
const serialize = reply
|
||||
.compileSerializationSchema({
|
||||
'3xx': {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
name: { type: 'string' },
|
||||
phone: { type: 'number' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, '3xx', 'application/json')
|
||||
serialize({ name: 'Jone', phone: 201090909090 }) // '{"name":"Jone", "phone":201090909090}'
|
||||
```
|
||||
|
||||
Note that you should be careful when using this function, as it will cache
|
||||
the compiled serialization functions based on the schema provided. If the
|
||||
schemas provided is mutated or changed, the serialization functions will not
|
||||
detect that the schema has been altered and for instance it will reuse the
|
||||
previously compiled serialization function based on the reference of the schema
|
||||
previously provided.
|
||||
|
||||
If there's a need to change the properties of a schema, always opt to create
|
||||
a totally new object, otherwise the implementation won't benefit from the cache
|
||||
mechanism.
|
||||
|
||||
:Using the following schema as example:
|
||||
```js
|
||||
const schema1 = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*Not*
|
||||
```js
|
||||
const serialize = reply.compileSerializationSchema(schema1)
|
||||
|
||||
// Later on...
|
||||
schema1.properties.foo.type. = 'integer'
|
||||
const newSerialize = reply.compileSerializationSchema(schema1)
|
||||
|
||||
console.log(newSerialize === serialize) // true
|
||||
```
|
||||
|
||||
*Instead*
|
||||
```js
|
||||
const serialize = reply.compileSerializationSchema(schema1)
|
||||
|
||||
// Later on...
|
||||
const newSchema = Object.assign({}, schema1)
|
||||
newSchema.properties.foo.type = 'integer'
|
||||
|
||||
const newSerialize = reply.compileSerializationSchema(newSchema)
|
||||
|
||||
console.log(newSerialize === serialize) // false
|
||||
```
|
||||
|
||||
### .serializeInput(data, [schema | httpStatus], [httpStatus], [contentType])
|
||||
<a id="serializeinput"></a>
|
||||
|
||||
This function will serialize the input data based on the provided schema
|
||||
or HTTP status code. If both are provided the `httpStatus` will take precedence.
|
||||
|
||||
If there is not a serialization function for a given `schema` a new serialization
|
||||
function will be compiled, forwarding the `httpStatus` and `contentType` if provided.
|
||||
|
||||
```js
|
||||
reply
|
||||
.serializeInput({ foo: 'bar'}, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}) // '{"foo":"bar"}'
|
||||
|
||||
// or
|
||||
|
||||
reply
|
||||
.serializeInput({ foo: 'bar'}, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}, 200) // '{"foo":"bar"}'
|
||||
|
||||
// or
|
||||
|
||||
reply
|
||||
.serializeInput({ foo: 'bar'}, 200) // '{"foo":"bar"}'
|
||||
|
||||
// or
|
||||
|
||||
reply
|
||||
.serializeInput({ name: 'Jone', age: 18 }, '200', 'application/vnd.v1+json') // '{"name": "Jone", "age": 18}'
|
||||
```
|
||||
|
||||
See [.compileSerializationSchema(schema, [httpStatus], [contentType])](#compileserializationschema)
|
||||
for more information on how to compile serialization schemas.
|
||||
|
||||
### .serializer(func)
|
||||
<a id="serializer"></a>
|
||||
|
||||
By default, `.send()` will JSON-serialize any value that is not one of `Buffer`,
|
||||
`stream`, `string`, `undefined`, or `Error`. If you need to replace the default
|
||||
serializer with a custom serializer for a particular request, you can do so with
|
||||
the `.serializer()` utility. Be aware that if you are using a custom serializer,
|
||||
you must set a custom `'Content-Type'` header.
|
||||
|
||||
```js
|
||||
reply
|
||||
.header('Content-Type', 'application/x-protobuf')
|
||||
.serializer(protoBuf.serialize)
|
||||
```
|
||||
|
||||
Note that you don't need to use this utility inside a `handler` because Buffers,
|
||||
streams, and strings (unless a serializer is set) are considered to already be
|
||||
serialized.
|
||||
|
||||
```js
|
||||
reply
|
||||
.header('Content-Type', 'application/x-protobuf')
|
||||
.send(protoBuf.serialize(data))
|
||||
```
|
||||
|
||||
See [`.send()`](#send) for more information on sending different types of
|
||||
values.
|
||||
|
||||
### .raw
|
||||
<a id="raw"></a>
|
||||
|
||||
This is the
|
||||
[`http.ServerResponse`](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_class_http_serverresponse)
|
||||
from Node core. Whilst you are using the Fastify `Reply` object, the use of
|
||||
`Reply.raw` functions is at your own risk as you are skipping all the Fastify
|
||||
logic of handling the HTTP response. e.g.:
|
||||
|
||||
```js
|
||||
app.get('/cookie-2', (req, reply) => {
|
||||
reply.setCookie('session', 'value', { secure: false }) // this will not be used
|
||||
|
||||
// in this case we are using only the nodejs http server response object
|
||||
reply.raw.writeHead(200, { 'Content-Type': 'text/plain' })
|
||||
reply.raw.write('ok')
|
||||
reply.raw.end()
|
||||
})
|
||||
```
|
||||
Another example of the misuse of `Reply.raw` is explained in
|
||||
[Reply](#getheaders).
|
||||
|
||||
### .sent
|
||||
<a id="sent"></a>
|
||||
|
||||
As the name suggests, `.sent` is a property to indicate if a response has been
|
||||
sent via `reply.send()`. It will also be `true` in case `reply.hijack()` was
|
||||
used.
|
||||
|
||||
In case a route handler is defined as an async function or it returns a promise,
|
||||
it is possible to call `reply.hijack()` to indicate that the automatic
|
||||
invocation of `reply.send()` once the handler promise resolve should be skipped.
|
||||
By calling `reply.hijack()`, an application claims full responsibility for the
|
||||
low-level request and response. Moreover, hooks will not be invoked.
|
||||
|
||||
*Modifying the `.sent` property directly is deprecated. Please use the
|
||||
aforementioned `.hijack()` method to achieve the same effect.*
|
||||
|
||||
### .hijack()
|
||||
<a name="hijack"></a>
|
||||
|
||||
Sometimes you might need to halt the execution of the normal request lifecycle
|
||||
and handle sending the response manually.
|
||||
|
||||
To achieve this, Fastify provides the `reply.hijack()` method that can be called
|
||||
during the request lifecycle (At any point before `reply.send()` is called), and
|
||||
allows you to prevent Fastify from sending the response, and from running the
|
||||
remaining hooks (and user handler if the reply was hijacked before).
|
||||
|
||||
```js
|
||||
app.get('/', (req, reply) => {
|
||||
reply.hijack()
|
||||
reply.raw.end('hello world')
|
||||
|
||||
return Promise.resolve('this will be skipped')
|
||||
})
|
||||
```
|
||||
|
||||
If `reply.raw` is used to send a response back to the user, the `onResponse`
|
||||
hooks will still be executed.
|
||||
|
||||
### .send(data)
|
||||
<a id="send"></a>
|
||||
|
||||
As the name suggests, `.send()` is the function that sends the payload to the
|
||||
end user.
|
||||
|
||||
#### Objects
|
||||
<a id="send-object"></a>
|
||||
|
||||
As noted above, if you are sending JSON objects, `send` will serialize the
|
||||
object with
|
||||
[fast-json-stringify](https://www.npmjs.com/package/fast-json-stringify) if you
|
||||
set an output schema, otherwise, `JSON.stringify()` will be used.
|
||||
```js
|
||||
fastify.get('/json', options, function (request, reply) {
|
||||
reply.send({ hello: 'world' })
|
||||
})
|
||||
```
|
||||
|
||||
#### Strings
|
||||
<a id="send-string"></a>
|
||||
|
||||
If you pass a string to `send` without a `Content-Type`, it will be sent as
|
||||
`text/plain; charset=utf-8`. If you set the `Content-Type` header and pass a
|
||||
string to `send`, it will be serialized with the custom serializer if one is
|
||||
set, otherwise, it will be sent unmodified (unless the `Content-Type` header is
|
||||
set to `application/json; charset=utf-8`, in which case it will be
|
||||
JSON-serialized like an object — see the section above).
|
||||
```js
|
||||
fastify.get('/json', options, function (request, reply) {
|
||||
reply.send('plain string')
|
||||
})
|
||||
```
|
||||
|
||||
#### Streams
|
||||
<a id="send-streams"></a>
|
||||
|
||||
If you are sending a stream and you have not set a `'Content-Type'` header,
|
||||
*send* will set it to `'application/octet-stream'`.
|
||||
|
||||
As noted above, streams are considered to be pre-serialized, so they will be
|
||||
sent unmodified without response validation.
|
||||
|
||||
```js
|
||||
fastify.get('/streams', function (request, reply) {
|
||||
const fs = require('node:fs')
|
||||
const stream = fs.createReadStream('some-file', 'utf8')
|
||||
reply.header('Content-Type', 'application/octet-stream')
|
||||
reply.send(stream)
|
||||
})
|
||||
```
|
||||
When using async-await you will need to return or await the reply object:
|
||||
```js
|
||||
fastify.get('/streams', async function (request, reply) {
|
||||
const fs = require('node:fs')
|
||||
const stream = fs.createReadStream('some-file', 'utf8')
|
||||
reply.header('Content-Type', 'application/octet-stream')
|
||||
return reply.send(stream)
|
||||
})
|
||||
```
|
||||
|
||||
#### Buffers
|
||||
<a id="send-buffers"></a>
|
||||
|
||||
If you are sending a buffer and you have not set a `'Content-Type'` header,
|
||||
*send* will set it to `'application/octet-stream'`.
|
||||
|
||||
As noted above, Buffers are considered to be pre-serialized, so they will be
|
||||
sent unmodified without response validation.
|
||||
|
||||
```js
|
||||
const fs = require('node:fs')
|
||||
fastify.get('/streams', function (request, reply) {
|
||||
fs.readFile('some-file', (err, fileBuffer) => {
|
||||
reply.send(err || fileBuffer)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
When using async-await you will need to return or await the reply object:
|
||||
```js
|
||||
const fs = require('node:fs')
|
||||
fastify.get('/streams', async function (request, reply) {
|
||||
fs.readFile('some-file', (err, fileBuffer) => {
|
||||
reply.send(err || fileBuffer)
|
||||
})
|
||||
return reply
|
||||
})
|
||||
```
|
||||
|
||||
#### TypedArrays
|
||||
<a id="send-typedarrays"></a>
|
||||
|
||||
`send` manages TypedArray like a Buffer, and sets the `'Content-Type'`
|
||||
header to `'application/octet-stream'` if not already set.
|
||||
|
||||
As noted above, TypedArray/Buffers are considered to be pre-serialized, so they
|
||||
will be sent unmodified without response validation.
|
||||
|
||||
```js
|
||||
const fs = require('node:fs')
|
||||
fastify.get('/streams', function (request, reply) {
|
||||
const typedArray = new Uint16Array(10)
|
||||
reply.send(typedArray)
|
||||
})
|
||||
```
|
||||
|
||||
#### ReadableStream
|
||||
<a id="send-readablestream"></a>
|
||||
|
||||
`ReadableStream` will be treated as a node stream mentioned above,
|
||||
the content is considered to be pre-serialized, so they will be
|
||||
sent unmodified without response validation.
|
||||
|
||||
```js
|
||||
const fs = require('node:fs')
|
||||
const { ReadableStream } = require('node:stream/web')
|
||||
fastify.get('/streams', function (request, reply) {
|
||||
const stream = fs.createReadStream('some-file')
|
||||
reply.header('Content-Type', 'application/octet-stream')
|
||||
reply.send(ReadableStream.from(stream))
|
||||
})
|
||||
```
|
||||
|
||||
#### Response
|
||||
<a id="send-response"></a>
|
||||
|
||||
`Response` allows to manage the reply payload, status code and
|
||||
headers in one place. The payload provided inside `Response` is
|
||||
considered to be pre-serialized, so they will be sent unmodified
|
||||
without response validation.
|
||||
|
||||
Please be aware when using `Response`, the status code and headers
|
||||
will not directly reflect to `reply.statusCode` and `reply.getHeaders()`.
|
||||
Such behavior is based on `Response` only allow `readonly` status
|
||||
code and headers. The data is not allow to be bi-direction editing,
|
||||
and may confuse when checking the `payload` in `onSend` hooks.
|
||||
|
||||
```js
|
||||
const fs = require('node:fs')
|
||||
const { ReadableStream } = require('node:stream/web')
|
||||
fastify.get('/streams', function (request, reply) {
|
||||
const stream = fs.createReadStream('some-file')
|
||||
const readableStream = ReadableStream.from(stream)
|
||||
const response = new Response(readableStream, {
|
||||
status: 200,
|
||||
headers: { 'content-type': 'application/octet-stream' }
|
||||
})
|
||||
reply.send(response)
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
#### Errors
|
||||
<a id="errors"></a>
|
||||
|
||||
If you pass to *send* an object that is an instance of *Error*, Fastify will
|
||||
automatically create an error structured as the following:
|
||||
|
||||
```js
|
||||
{
|
||||
error: String // the HTTP error message
|
||||
code: String // the Fastify error code
|
||||
message: String // the user error message
|
||||
statusCode: Number // the HTTP status code
|
||||
}
|
||||
```
|
||||
|
||||
You can add custom properties to the Error object, such as `headers`, that will
|
||||
be used to enhance the HTTP response.
|
||||
|
||||
*Note: If you are passing an error to `send` and the statusCode is less than
|
||||
400, Fastify will automatically set it at 500.*
|
||||
|
||||
Tip: you can simplify errors by using the
|
||||
[`http-errors`](https://npm.im/http-errors) module or
|
||||
[`@fastify/sensible`](https://github.com/fastify/fastify-sensible) plugin to
|
||||
generate errors:
|
||||
|
||||
```js
|
||||
fastify.get('/', function (request, reply) {
|
||||
reply.send(httpErrors.Gone())
|
||||
})
|
||||
```
|
||||
|
||||
To customize the JSON error output you can do it by:
|
||||
|
||||
- setting a response JSON schema for the status code you need
|
||||
- add the additional properties to the `Error` instance
|
||||
|
||||
Notice that if the returned status code is not in the response schema list, the
|
||||
default behavior will be applied.
|
||||
|
||||
```js
|
||||
fastify.get('/', {
|
||||
schema: {
|
||||
response: {
|
||||
501: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
statusCode: { type: 'number' },
|
||||
code: { type: 'string' },
|
||||
error: { type: 'string' },
|
||||
message: { type: 'string' },
|
||||
time: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, function (request, reply) {
|
||||
const error = new Error('This endpoint has not been implemented')
|
||||
error.time = 'it will be implemented in two weeks'
|
||||
reply.code(501).send(error)
|
||||
})
|
||||
```
|
||||
|
||||
If you want to customize error handling, check out
|
||||
[`setErrorHandler`](./Server.md#seterrorhandler) API.
|
||||
|
||||
*Note: you are responsible for logging when customizing the error handler*
|
||||
|
||||
API:
|
||||
|
||||
```js
|
||||
fastify.setErrorHandler(function (error, request, reply) {
|
||||
request.log.warn(error)
|
||||
var statusCode = error.statusCode >= 400 ? error.statusCode : 500
|
||||
reply
|
||||
.code(statusCode)
|
||||
.type('text/plain')
|
||||
.send(statusCode >= 500 ? 'Internal server error' : error.message)
|
||||
})
|
||||
```
|
||||
|
||||
Beware that calling `reply.send(error)` in your custom error handler will send
|
||||
the error to the default error handler.
|
||||
Check out the [Reply Lifecycle](./Lifecycle.md#reply-lifecycle)
|
||||
for more information.
|
||||
|
||||
The not found errors generated by the router will use the
|
||||
[`setNotFoundHandler`](./Server.md#setnotfoundhandler)
|
||||
|
||||
API:
|
||||
|
||||
```js
|
||||
fastify.setNotFoundHandler(function (request, reply) {
|
||||
reply
|
||||
.code(404)
|
||||
.type('text/plain')
|
||||
.send('a custom not found')
|
||||
})
|
||||
```
|
||||
|
||||
#### Type of the final payload
|
||||
<a id="payload-type"></a>
|
||||
|
||||
The type of the sent payload (after serialization and going through any
|
||||
[`onSend` hooks](./Hooks.md#onsend)) must be one of the following types,
|
||||
otherwise, an error will be thrown:
|
||||
|
||||
- `string`
|
||||
- `Buffer`
|
||||
- `stream`
|
||||
- `undefined`
|
||||
- `null`
|
||||
|
||||
#### Async-Await and Promises
|
||||
<a id="async-await-promise"></a>
|
||||
|
||||
Fastify natively handles promises and supports async-await.
|
||||
|
||||
*Note that in the following examples we are not using reply.send.*
|
||||
```js
|
||||
const { promisify } = require('node:util')
|
||||
const delay = promisify(setTimeout)
|
||||
|
||||
fastify.get('/promises', options, function (request, reply) {
|
||||
return delay(200).then(() => { return { hello: 'world' }})
|
||||
})
|
||||
|
||||
fastify.get('/async-await', options, async function (request, reply) {
|
||||
await delay(200)
|
||||
return { hello: 'world' }
|
||||
})
|
||||
```
|
||||
|
||||
Rejected promises default to a `500` HTTP status code. Reject the promise, or
|
||||
`throw` in an `async function`, with an object that has `statusCode` (or
|
||||
`status`) and `message` properties to modify the reply.
|
||||
|
||||
```js
|
||||
fastify.get('/teapot', async function (request, reply) {
|
||||
const err = new Error()
|
||||
err.statusCode = 418
|
||||
err.message = 'short and stout'
|
||||
throw err
|
||||
})
|
||||
|
||||
fastify.get('/botnet', async function (request, reply) {
|
||||
throw { statusCode: 418, message: 'short and stout' }
|
||||
// will return to the client the same json
|
||||
})
|
||||
```
|
||||
|
||||
If you want to know more please review
|
||||
[Routes#async-await](./Routes.md#async-await).
|
||||
|
||||
### .then(fulfilled, rejected)
|
||||
<a id="then"></a>
|
||||
|
||||
As the name suggests, a `Reply` object can be awaited upon, i.e. `await reply`
|
||||
will wait until the reply is sent. The `await` syntax calls the `reply.then()`.
|
||||
|
||||
`reply.then(fulfilled, rejected)` accepts two parameters:
|
||||
|
||||
- `fulfilled` will be called when a response has been fully sent,
|
||||
- `rejected` will be called if the underlying stream had an error, e.g. the
|
||||
socket has been destroyed.
|
||||
|
||||
For more details, see:
|
||||
|
||||
- https://github.com/fastify/fastify/issues/1864 for the discussion about this
|
||||
feature
|
||||
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
|
||||
for the signature
|
||||
289
backend/node_modules/fastify/docs/Reference/Request.md
generated
vendored
Normal file
289
backend/node_modules/fastify/docs/Reference/Request.md
generated
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Request
|
||||
The first parameter of the handler function is `Request`.
|
||||
|
||||
Request is a core Fastify object containing the following fields:
|
||||
- `query` - the parsed querystring, its format is specified by
|
||||
[`querystringParser`](./Server.md#querystringparser)
|
||||
- `body` - the request payload, see [Content-Type
|
||||
Parser](./ContentTypeParser.md) for details on what request payloads Fastify
|
||||
natively parses and how to support other content types
|
||||
- `params` - the params matching the URL
|
||||
- [`headers`](#headers) - the headers getter and setter
|
||||
- `raw` - the incoming HTTP request from Node core
|
||||
- `server` - The Fastify server instance, scoped to the current [encapsulation
|
||||
context](./Encapsulation.md)
|
||||
- `id` - the request ID
|
||||
- `log` - the logger instance of the incoming request
|
||||
- `ip` - the IP address of the incoming request
|
||||
- `ips` - an array of the IP addresses, ordered from closest to furthest, in the
|
||||
`X-Forwarded-For` header of the incoming request (only when the
|
||||
[`trustProxy`](./Server.md#factory-trust-proxy) option is enabled)
|
||||
- `hostname` - the host of the incoming request (derived from `X-Forwarded-Host`
|
||||
header when the [`trustProxy`](./Server.md#factory-trust-proxy) option is
|
||||
enabled). For HTTP/2 compatibility it returns `:authority` if no host header
|
||||
exists.
|
||||
- `protocol` - the protocol of the incoming request (`https` or `http`)
|
||||
- `method` - the method of the incoming request
|
||||
- `url` - the URL of the incoming request
|
||||
- `originalUrl` - similar to `url`, this allows you to access the
|
||||
original `url` in case of internal re-routing
|
||||
- `routerMethod` - Deprecated, use `request.routeOptions.method` instead. The
|
||||
method defined for the router that is handling the request
|
||||
- `routerPath` - Deprecated, use `request.routeOptions.url` instead. The
|
||||
path pattern defined for the router that is handling the request
|
||||
- `is404` - true if request is being handled by 404 handler, false if it is not
|
||||
- `connection` - Deprecated, use `socket` instead. The underlying connection of
|
||||
the incoming request.
|
||||
- `socket` - the underlying connection of the incoming request
|
||||
- `context` - Deprecated, use `request.routeOptions.config` instead.
|
||||
A Fastify internal object. You should not use
|
||||
it directly or modify it. It is useful to access one special key:
|
||||
- `context.config` - The route [`config`](./Routes.md#routes-config) object.
|
||||
- `routeSchema` - Deprecated, use `request.routeOptions.schema` instead. The
|
||||
scheme definition set for the router that is handling the request
|
||||
- `routeConfig` - Deprecated, use `request.routeOptions.config` instead. The
|
||||
route [`config`](./Routes.md#routes-config)
|
||||
object.
|
||||
- `routeOptions` - The route [`option`](./Routes.md#routes-options) object
|
||||
- `bodyLimit` - either server limit or route limit
|
||||
- `config` - the [`config`](./Routes.md#routes-config) object for this route
|
||||
- `method` - the http method for the route
|
||||
- `url` - the path of the URL to match this route
|
||||
- `handler` - the handler for this route
|
||||
- `attachValidation` - attach `validationError` to request
|
||||
(if there is a schema defined)
|
||||
- `logLevel` - log level defined for this route
|
||||
- `schema` - the JSON schemas definition for this route
|
||||
- `version` - a semver compatible string that defines the version of the endpoint
|
||||
- `exposeHeadRoute` - creates a sibling HEAD route for any GET routes
|
||||
- `prefixTrailingSlash` - string used to determine how to handle passing /
|
||||
as a route with a prefix.
|
||||
- [.getValidationFunction(schema | httpPart)](#getvalidationfunction) -
|
||||
Returns a validation function for the specified schema or http part,
|
||||
if any of either are set or cached.
|
||||
- [.compileValidationSchema(schema, [httpPart])](#compilevalidationschema) -
|
||||
Compiles the specified schema and returns a validation function
|
||||
using the default (or customized) `ValidationCompiler`.
|
||||
The optional `httpPart` is forwarded to the `ValidationCompiler`
|
||||
if provided, defaults to `null`.
|
||||
- [.validateInput(data, schema | httpPart, [httpPart])](#validate) -
|
||||
Validates the specified input by using the specified
|
||||
schema and returns the serialized payload. If the optional
|
||||
`httpPart` is provided, the function will use the serializer
|
||||
function given for that HTTP Status Code. Defaults to `null`.
|
||||
|
||||
### Headers
|
||||
|
||||
The `request.headers` is a getter that returns an Object with the headers of the
|
||||
incoming request. You can set custom headers like this:
|
||||
|
||||
```js
|
||||
request.headers = {
|
||||
'foo': 'bar',
|
||||
'baz': 'qux'
|
||||
}
|
||||
```
|
||||
|
||||
This operation will add to the request headers the new values that can be read
|
||||
calling `request.headers.bar`. Moreover, you can still access the standard
|
||||
request's headers with the `request.raw.headers` property.
|
||||
|
||||
> Note: For performance reason on `not found` route, you may see that we will
|
||||
add an extra property `Symbol('fastify.RequestAcceptVersion')` on the headers.
|
||||
|
||||
```js
|
||||
fastify.post('/:params', options, function (request, reply) {
|
||||
console.log(request.body)
|
||||
console.log(request.query)
|
||||
console.log(request.params)
|
||||
console.log(request.headers)
|
||||
console.log(request.raw)
|
||||
console.log(request.server)
|
||||
console.log(request.id)
|
||||
console.log(request.ip)
|
||||
console.log(request.ips)
|
||||
console.log(request.hostname)
|
||||
console.log(request.protocol)
|
||||
console.log(request.url)
|
||||
console.log(request.routeOptions.method)
|
||||
console.log(request.routeOptions.bodyLimit)
|
||||
console.log(request.routeOptions.method)
|
||||
console.log(request.routeOptions.url)
|
||||
console.log(request.routeOptions.attachValidation)
|
||||
console.log(request.routeOptions.logLevel)
|
||||
console.log(request.routeOptions.version)
|
||||
console.log(request.routeOptions.exposeHeadRoute)
|
||||
console.log(request.routeOptions.prefixTrailingSlash)
|
||||
console.log(request.routeOptions.logLevel)
|
||||
request.log.info('some info')
|
||||
})
|
||||
```
|
||||
### .getValidationFunction(schema | httpPart)
|
||||
<a id="getvalidationfunction"></a>
|
||||
|
||||
By calling this function using a provided `schema` or `httpPart`,
|
||||
it will return a `validation` function that can be used to
|
||||
validate diverse inputs. It returns `undefined` if no
|
||||
serialization function was found using either of the provided inputs.
|
||||
|
||||
This function has property errors. Errors encountered during the last validation
|
||||
are assigned to errors
|
||||
|
||||
```js
|
||||
const validate = request
|
||||
.getValidationFunction({
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
})
|
||||
console.log(validate({ foo: 'bar' })) // true
|
||||
console.log(validate.errors) // null
|
||||
|
||||
// or
|
||||
|
||||
const validate = request
|
||||
.getValidationFunction('body')
|
||||
console.log(validate({ foo: 0.5 })) // false
|
||||
console.log(validate.errors) // validation errors
|
||||
```
|
||||
|
||||
See [.compileValidationSchema(schema, [httpStatus])](#compilevalidationschema)
|
||||
for more information on how to compile validation function.
|
||||
|
||||
### .compileValidationSchema(schema, [httpPart])
|
||||
<a id="compilevalidationschema"></a>
|
||||
|
||||
This function will compile a validation schema and
|
||||
return a function that can be used to validate data.
|
||||
The function returned (a.k.a. _validation function_) is compiled
|
||||
by using the provided [`SchemaController#ValidationCompiler`](./Server.md#schema-controller).
|
||||
A `WeakMap` is used to cached this, reducing compilation calls.
|
||||
|
||||
The optional parameter `httpPart`, if provided, is forwarded directly
|
||||
the `ValidationCompiler`, so it can be used to compile the validation
|
||||
function if a custom `ValidationCompiler` is provided for the route.
|
||||
|
||||
This function has property errors. Errors encountered during the last validation
|
||||
are assigned to errors
|
||||
|
||||
```js
|
||||
const validate = request
|
||||
.compileValidationSchema({
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
})
|
||||
console.log(validate({ foo: 'bar' })) // true
|
||||
console.log(validate.errors) // null
|
||||
|
||||
// or
|
||||
|
||||
const validate = request
|
||||
.compileValidationSchema({
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}, 200)
|
||||
console.log(validate({ hello: 'world' })) // false
|
||||
console.log(validate.errors) // validation errors
|
||||
```
|
||||
|
||||
Note that you should be careful when using this function, as it will cache
|
||||
the compiled validation functions based on the schema provided. If the
|
||||
schemas provided are mutated or changed, the validation functions will not
|
||||
detect that the schema has been altered and for instance it will reuse the
|
||||
previously compiled validation function, as the cache is based on
|
||||
the reference of the schema (Object) previously provided.
|
||||
|
||||
If there is a need to change the properties of a schema, always opt to create
|
||||
a totally new schema (object), otherwise the implementation will not benefit from
|
||||
the cache mechanism.
|
||||
|
||||
Using the following schema as an example:
|
||||
```js
|
||||
const schema1 = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
*Not*
|
||||
```js
|
||||
const validate = request.compileValidationSchema(schema1)
|
||||
|
||||
// Later on...
|
||||
schema1.properties.foo.type. = 'integer'
|
||||
const newValidate = request.compileValidationSchema(schema1)
|
||||
|
||||
console.log(newValidate === validate) // true
|
||||
```
|
||||
|
||||
*Instead*
|
||||
```js
|
||||
const validate = request.compileValidationSchema(schema1)
|
||||
|
||||
// Later on...
|
||||
const newSchema = Object.assign({}, schema1)
|
||||
newSchema.properties.foo.type = 'integer'
|
||||
|
||||
const newValidate = request.compileValidationSchema(newSchema)
|
||||
|
||||
console.log(newValidate === validate) // false
|
||||
```
|
||||
|
||||
### .validateInput(data, [schema | httpStatus], [httpStatus])
|
||||
<a id="validate"></a>
|
||||
|
||||
This function will validate the input based on the provided schema,
|
||||
or HTTP part passed. If both are provided, the `httpPart` parameter
|
||||
will take precedence.
|
||||
|
||||
If there is not a validation function for a given `schema`, a new validation
|
||||
function will be compiled, forwarding the `httpPart` if provided.
|
||||
|
||||
```js
|
||||
request
|
||||
.validateInput({ foo: 'bar'}, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}) // true
|
||||
|
||||
// or
|
||||
|
||||
request
|
||||
.validateInput({ foo: 'bar'}, {
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
}, 'body') // true
|
||||
|
||||
// or
|
||||
|
||||
request
|
||||
.validateInput({ hello: 'world'}, 'query') // false
|
||||
```
|
||||
|
||||
See [.compileValidationSchema(schema, [httpStatus])](#compileValidationSchema)
|
||||
for more information on how to compile validation schemas.
|
||||
834
backend/node_modules/fastify/docs/Reference/Routes.md
generated
vendored
Normal file
834
backend/node_modules/fastify/docs/Reference/Routes.md
generated
vendored
Normal file
@@ -0,0 +1,834 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Routes
|
||||
|
||||
The route methods will configure the endpoints of your application. You have two
|
||||
ways to declare a route with Fastify: the shorthand method and the full
|
||||
declaration.
|
||||
|
||||
- [Full declaration](#full-declaration)
|
||||
- [Routes options](#routes-options)
|
||||
- [Shorthand declaration](#shorthand-declaration)
|
||||
- [Url building](#url-building)
|
||||
- [Async Await](#async-await)
|
||||
- [Promise resolution](#promise-resolution)
|
||||
- [Route Prefixing](#route-prefixing)
|
||||
- [Handling of / route inside prefixed
|
||||
plugins](#handling-of--route-inside-prefixed-plugins)
|
||||
- [Custom Log Level](#custom-log-level)
|
||||
- [Custom Log Serializer](#custom-log-serializer)
|
||||
- [Config](#config)
|
||||
- [Constraints](#constraints)
|
||||
- [Version Constraints](#version-constraints)
|
||||
- [Host Constraints](#host-constraints)
|
||||
|
||||
### Full declaration
|
||||
<a id="full-declaration"></a>
|
||||
|
||||
```js
|
||||
fastify.route(options)
|
||||
```
|
||||
|
||||
### Routes options
|
||||
<a id="options"></a>
|
||||
|
||||
* `method`: currently it supports `'DELETE'`, `'GET'`, `'HEAD'`, `'PATCH'`,
|
||||
`'POST'`, `'PUT'`, `'OPTIONS'`, `'SEARCH'`, `'TRACE'`, `'PROPFIND'`,
|
||||
`'PROPPATCH'`, `'MKCOL'`, `'COPY'`, `'MOVE'`, `'LOCK'`, `'UNLOCK'`,
|
||||
`'REPORT'` and `'MKCALENDAR'`.
|
||||
It could also be an array of methods.
|
||||
* `url`: the path of the URL to match this route (alias: `path`).
|
||||
* `schema`: an object containing the schemas for the request and response. They
|
||||
need to be in [JSON Schema](https://json-schema.org/) format, check
|
||||
[here](./Validation-and-Serialization.md) for more info.
|
||||
|
||||
* `body`: validates the body of the request if it is a POST, PUT, PATCH,
|
||||
TRACE, SEARCH, PROPFIND, PROPPATCH, COPY, MOVE, MKCOL, REPORT, MKCALENDAR
|
||||
or LOCK method.
|
||||
* `querystring` or `query`: validates the querystring. This can be a complete
|
||||
JSON Schema object, with the property `type` of `object` and `properties`
|
||||
object of parameters, or simply the values of what would be contained in the
|
||||
`properties` object as shown below.
|
||||
* `params`: validates the params.
|
||||
* `response`: filter and generate a schema for the response, setting a schema
|
||||
allows us to have 10-20% more throughput.
|
||||
* `exposeHeadRoute`: creates a sibling `HEAD` route for any `GET` routes.
|
||||
Defaults to the value of [`exposeHeadRoutes`](./Server.md#exposeHeadRoutes)
|
||||
instance option. If you want a custom `HEAD` handler without disabling this
|
||||
option, make sure to define it before the `GET` route.
|
||||
* `attachValidation`: attach `validationError` to request, if there is a schema
|
||||
validation error, instead of sending the error to the error handler. The
|
||||
default [error format](https://ajv.js.org/api.html#error-objects) is the Ajv
|
||||
one.
|
||||
* `onRequest(request, reply, done)`: a [function](./Hooks.md#onrequest) called
|
||||
as soon as a request is received, it could also be an array of functions.
|
||||
* `preParsing(request, reply, done)`: a [function](./Hooks.md#preparsing) called
|
||||
before parsing the request, it could also be an array of functions.
|
||||
* `preValidation(request, reply, done)`: a [function](./Hooks.md#prevalidation)
|
||||
called after the shared `preValidation` hooks, useful if you need to perform
|
||||
authentication at route level for example, it could also be an array of
|
||||
functions.
|
||||
* `preHandler(request, reply, done)`: a [function](./Hooks.md#prehandler) called
|
||||
just before the request handler, it could also be an array of functions.
|
||||
* `preSerialization(request, reply, payload, done)`: a
|
||||
[function](./Hooks.md#preserialization) called just before the serialization,
|
||||
it could also be an array of functions.
|
||||
* `onSend(request, reply, payload, done)`: a [function](./Hooks.md#route-hooks)
|
||||
called right before a response is sent, it could also be an array of
|
||||
functions.
|
||||
* `onResponse(request, reply, done)`: a [function](./Hooks.md#onresponse) called
|
||||
when a response has been sent, so you will not be able to send more data to
|
||||
the client. It could also be an array of functions.
|
||||
* `onTimeout(request, reply, done)`: a [function](./Hooks.md#ontimeout) called
|
||||
when a request is timed out and the HTTP socket has been hung up.
|
||||
* `onError(request, reply, error, done)`: a [function](./Hooks.md#onerror)
|
||||
called when an Error is thrown or sent to the client by the route handler.
|
||||
* `handler(request, reply)`: the function that will handle this request. The
|
||||
[Fastify server](./Server.md) will be bound to `this` when the handler is
|
||||
called. Note: using an arrow function will break the binding of `this`.
|
||||
* `errorHandler(error, request, reply)`: a custom error handler for the scope of
|
||||
the request. Overrides the default error global handler, and anything set by
|
||||
[`setErrorHandler`](./Server.md#seterrorhandler), for requests to the route.
|
||||
To access the default handler, you can access `instance.errorHandler`. Note
|
||||
that this will point to fastify's default `errorHandler` only if a plugin
|
||||
hasn't overridden it already.
|
||||
* `childLoggerFactory(logger, binding, opts, rawReq)`: a custom factory function
|
||||
that will be called to produce a child logger instance for every request.
|
||||
See [`childLoggerFactory`](./Server.md#childloggerfactory) for more info.
|
||||
Overrides the default logger factory, and anything set by
|
||||
[`setChildLoggerFactory`](./Server.md#setchildloggerfactory), for requests to
|
||||
the route. To access the default factory, you can access
|
||||
`instance.childLoggerFactory`. Note that this will point to Fastify's default
|
||||
`childLoggerFactory` only if a plugin hasn't overridden it already.
|
||||
* `validatorCompiler({ schema, method, url, httpPart })`: function that builds
|
||||
schemas for request validations. See the [Validation and
|
||||
Serialization](./Validation-and-Serialization.md#schema-validator)
|
||||
documentation.
|
||||
* `serializerCompiler({ { schema, method, url, httpStatus, contentType } })`:
|
||||
function that builds schemas for response serialization. See the [Validation and
|
||||
Serialization](./Validation-and-Serialization.md#schema-serializer)
|
||||
documentation.
|
||||
* `schemaErrorFormatter(errors, dataVar)`: function that formats the errors from
|
||||
the validation compiler. See the [Validation and
|
||||
Serialization](./Validation-and-Serialization.md#error-handling)
|
||||
documentation. Overrides the global schema error formatter handler, and
|
||||
anything set by `setSchemaErrorFormatter`, for requests to the route.
|
||||
* `bodyLimit`: prevents the default JSON body parser from parsing request bodies
|
||||
larger than this number of bytes. Must be an integer. You may also set this
|
||||
option globally when first creating the Fastify instance with
|
||||
`fastify(options)`. Defaults to `1048576` (1 MiB).
|
||||
* `logLevel`: set log level for this route. See below.
|
||||
* `logSerializers`: set serializers to log for this route.
|
||||
* `config`: object used to store custom configuration.
|
||||
* `version`: a [semver](https://semver.org/) compatible string that defined the
|
||||
version of the endpoint. [Example](#version-constraints).
|
||||
* `constraints`: defines route restrictions based on request properties or
|
||||
values, enabling customized matching using
|
||||
[find-my-way](https://github.com/delvedor/find-my-way) constraints. Includes
|
||||
built-in `version` and `host` constraints, with support for custom constraint
|
||||
strategies.
|
||||
* `prefixTrailingSlash`: string used to determine how to handle passing `/` as a
|
||||
route with a prefix.
|
||||
* `both` (default): Will register both `/prefix` and `/prefix/`.
|
||||
* `slash`: Will register only `/prefix/`.
|
||||
* `no-slash`: Will register only `/prefix`.
|
||||
|
||||
Note: this option does not override `ignoreTrailingSlash` in
|
||||
[Server](./Server.md) configuration.
|
||||
|
||||
* `request` is defined in [Request](./Request.md).
|
||||
|
||||
* `reply` is defined in [Reply](./Reply.md).
|
||||
|
||||
**Notice:** The documentation of `onRequest`, `preParsing`, `preValidation`,
|
||||
`preHandler`, `preSerialization`, `onSend`, and `onResponse` are described in
|
||||
more detail in [Hooks](./Hooks.md). Additionally, to send a response before the
|
||||
request is handled by the `handler` please refer to [Respond to a request from a
|
||||
hook](./Hooks.md#respond-to-a-request-from-a-hook).
|
||||
|
||||
Example:
|
||||
```js
|
||||
fastify.route({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
schema: {
|
||||
querystring: {
|
||||
name: { type: 'string' },
|
||||
excitement: { type: 'integer' }
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
handler: function (request, reply) {
|
||||
reply.send({ hello: 'world' })
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Shorthand declaration
|
||||
<a id="shorthand-declaration"></a>
|
||||
|
||||
The above route declaration is more *Hapi*-like, but if you prefer an
|
||||
*Express/Restify* approach, we support it as well:
|
||||
|
||||
`fastify.get(path, [options], handler)`
|
||||
|
||||
`fastify.head(path, [options], handler)`
|
||||
|
||||
`fastify.post(path, [options], handler)`
|
||||
|
||||
`fastify.put(path, [options], handler)`
|
||||
|
||||
`fastify.delete(path, [options], handler)`
|
||||
|
||||
`fastify.options(path, [options], handler)`
|
||||
|
||||
`fastify.patch(path, [options], handler)`
|
||||
|
||||
Example:
|
||||
```js
|
||||
const opts = {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fastify.get('/', opts, (request, reply) => {
|
||||
reply.send({ hello: 'world' })
|
||||
})
|
||||
```
|
||||
|
||||
`fastify.all(path, [options], handler)` will add the same handler to all the
|
||||
supported methods.
|
||||
|
||||
The handler may also be supplied via the `options` object:
|
||||
```js
|
||||
const opts = {
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hello: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
handler: function (request, reply) {
|
||||
reply.send({ hello: 'world' })
|
||||
}
|
||||
}
|
||||
fastify.get('/', opts)
|
||||
```
|
||||
|
||||
> Note: if the handler is specified in both the `options` and as the third
|
||||
> parameter to the shortcut method then throws a duplicate `handler` error.
|
||||
|
||||
### Url building
|
||||
<a id="url-building"></a>
|
||||
|
||||
Fastify supports both static and dynamic URLs.
|
||||
|
||||
To register a **parametric** path, use the *colon* before the parameter name.
|
||||
For **wildcard**, use the *star*. *Remember that static routes are always
|
||||
checked before parametric and wildcard.*
|
||||
|
||||
```js
|
||||
// parametric
|
||||
fastify.get('/example/:userId', function (request, reply) {
|
||||
// curl ${app-url}/example/12345
|
||||
// userId === '12345'
|
||||
const { userId } = request.params;
|
||||
// your code here
|
||||
})
|
||||
fastify.get('/example/:userId/:secretToken', function (request, reply) {
|
||||
// curl ${app-url}/example/12345/abc.zHi
|
||||
// userId === '12345'
|
||||
// secretToken === 'abc.zHi'
|
||||
const { userId, secretToken } = request.params;
|
||||
// your code here
|
||||
})
|
||||
|
||||
// wildcard
|
||||
fastify.get('/example/*', function (request, reply) {})
|
||||
```
|
||||
|
||||
Regular expression routes are supported as well, but be aware that you have to
|
||||
escape slashes. Take note that RegExp is also very expensive in terms of
|
||||
performance!
|
||||
```js
|
||||
// parametric with regexp
|
||||
fastify.get('/example/:file(^\\d+).png', function (request, reply) {
|
||||
// curl ${app-url}/example/12345.png
|
||||
// file === '12345'
|
||||
const { file } = request.params;
|
||||
// your code here
|
||||
})
|
||||
```
|
||||
|
||||
It is possible to define more than one parameter within the same couple of slash
|
||||
("/"). Such as:
|
||||
```js
|
||||
fastify.get('/example/near/:lat-:lng/radius/:r', function (request, reply) {
|
||||
// curl ${app-url}/example/near/15°N-30°E/radius/20
|
||||
// lat === "15°N"
|
||||
// lng === "30°E"
|
||||
// r ==="20"
|
||||
const { lat, lng, r } = request.params;
|
||||
// your code here
|
||||
})
|
||||
```
|
||||
*Remember in this case to use the dash ("-") as parameters separator.*
|
||||
|
||||
Finally, it is possible to have multiple parameters with RegExp:
|
||||
```js
|
||||
fastify.get('/example/at/:hour(^\\d{2})h:minute(^\\d{2})m', function (request, reply) {
|
||||
// curl ${app-url}/example/at/08h24m
|
||||
// hour === "08"
|
||||
// minute === "24"
|
||||
const { hour, minute } = request.params;
|
||||
// your code here
|
||||
})
|
||||
```
|
||||
In this case as parameter separator it is possible to use whatever character is
|
||||
not matched by the regular expression.
|
||||
|
||||
The last parameter can be made optional if you add a question mark ("?") to the
|
||||
end of the parameters name.
|
||||
```js
|
||||
fastify.get('/example/posts/:id?', function (request, reply) {
|
||||
const { id } = request.params;
|
||||
// your code here
|
||||
})
|
||||
```
|
||||
In this case you can request `/example/posts` as well as `/example/posts/1`.
|
||||
The optional param will be undefined if not specified.
|
||||
|
||||
Having a route with multiple parameters may negatively affect performance, so
|
||||
prefer a single parameter approach whenever possible, especially on routes that
|
||||
are on the hot path of your application. If you are interested in how we handle
|
||||
the routing, check out [find-my-way](https://github.com/delvedor/find-my-way).
|
||||
|
||||
If you want a path containing a colon without declaring a parameter, use a
|
||||
double colon. For example:
|
||||
```js
|
||||
fastify.post('/name::verb') // will be interpreted as /name:verb
|
||||
```
|
||||
|
||||
### Async Await
|
||||
<a id="async-await"></a>
|
||||
|
||||
Are you an `async/await` user? We have you covered!
|
||||
```js
|
||||
fastify.get('/', options, async function (request, reply) {
|
||||
var data = await getData()
|
||||
var processed = await processData(data)
|
||||
return processed
|
||||
})
|
||||
```
|
||||
|
||||
As you can see, we are not calling `reply.send` to send back the data to the
|
||||
user. You just need to return the body and you are done!
|
||||
|
||||
If you need it you can also send back the data to the user with `reply.send`. In
|
||||
this case do not forget to `return reply` or `await reply` in your `async`
|
||||
handler or you will introduce a race condition in certain situations.
|
||||
|
||||
```js
|
||||
fastify.get('/', options, async function (request, reply) {
|
||||
var data = await getData()
|
||||
var processed = await processData(data)
|
||||
return reply.send(processed)
|
||||
})
|
||||
```
|
||||
|
||||
If the route is wrapping a callback-based API that will call `reply.send()`
|
||||
outside of the promise chain, it is possible to `await reply`:
|
||||
|
||||
```js
|
||||
fastify.get('/', options, async function (request, reply) {
|
||||
setImmediate(() => {
|
||||
reply.send({ hello: 'world' })
|
||||
})
|
||||
await reply
|
||||
})
|
||||
```
|
||||
|
||||
Returning reply also works:
|
||||
|
||||
```js
|
||||
fastify.get('/', options, async function (request, reply) {
|
||||
setImmediate(() => {
|
||||
reply.send({ hello: 'world' })
|
||||
})
|
||||
return reply
|
||||
})
|
||||
```
|
||||
|
||||
**Warning:**
|
||||
* When using both `return value` and `reply.send(value)` at the same time, the
|
||||
first one that happens takes precedence, the second value will be discarded,
|
||||
and a *warn* log will also be emitted because you tried to send a response
|
||||
twice.
|
||||
* Calling `reply.send()` outside of the promise is possible but requires special
|
||||
attention. For more details read [promise-resolution](#promise-resolution).
|
||||
* You cannot return `undefined`. For more details read
|
||||
[promise-resolution](#promise-resolution).
|
||||
|
||||
### Promise resolution
|
||||
<a id="promise-resolution"></a>
|
||||
|
||||
If your handler is an `async` function or returns a promise, you should be aware
|
||||
of the special behavior that is necessary to support the callback and promise
|
||||
control-flow. When the handler's promise is resolved, the reply will be
|
||||
automatically sent with its value unless you explicitly await or return `reply`
|
||||
in your handler.
|
||||
|
||||
1. If you want to use `async/await` or promises but respond with a value with
|
||||
`reply.send`:
|
||||
- **Do** `return reply` / `await reply`.
|
||||
- **Do not** forget to call `reply.send`.
|
||||
2. If you want to use `async/await` or promises:
|
||||
- **Do not** use `reply.send`.
|
||||
- **Do** return the value that you want to send.
|
||||
|
||||
In this way, we can support both `callback-style` and `async-await`, with the
|
||||
minimum trade-off. Despite so much freedom we highly recommend going with only
|
||||
one style because error handling should be handled in a consistent way within
|
||||
your application.
|
||||
|
||||
**Notice**: Every async function returns a promise by itself.
|
||||
|
||||
### Route Prefixing
|
||||
<a id="route-prefixing"></a>
|
||||
|
||||
Sometimes you need to maintain two or more different versions of the same API; a
|
||||
classic approach is to prefix all the routes with the API version number,
|
||||
`/v1/user` for example. Fastify offers you a fast and smart way to create
|
||||
different versions of the same API without changing all the route names by hand,
|
||||
*route prefixing*. Let's see how it works:
|
||||
|
||||
```js
|
||||
// server.js
|
||||
const fastify = require('fastify')()
|
||||
|
||||
fastify.register(require('./routes/v1/users'), { prefix: '/v1' })
|
||||
fastify.register(require('./routes/v2/users'), { prefix: '/v2' })
|
||||
|
||||
fastify.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
```js
|
||||
// routes/v1/users.js
|
||||
module.exports = function (fastify, opts, done) {
|
||||
fastify.get('/user', handler_v1)
|
||||
done()
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
// routes/v2/users.js
|
||||
module.exports = function (fastify, opts, done) {
|
||||
fastify.get('/user', handler_v2)
|
||||
done()
|
||||
}
|
||||
```
|
||||
Fastify will not complain because you are using the same name for two different
|
||||
routes, because at compilation time it will handle the prefix automatically
|
||||
*(this also means that the performance will not be affected at all!)*.
|
||||
|
||||
Now your clients will have access to the following routes:
|
||||
- `/v1/user`
|
||||
- `/v2/user`
|
||||
|
||||
You can do this as many times as you want, it also works for nested `register`,
|
||||
and route parameters are supported as well.
|
||||
|
||||
In case you want to use prefix for all of your routes, you can put them inside a
|
||||
plugin:
|
||||
|
||||
```js
|
||||
const fastify = require('fastify')()
|
||||
|
||||
const route = {
|
||||
method: 'POST',
|
||||
url: '/login',
|
||||
handler: () => {},
|
||||
schema: {},
|
||||
}
|
||||
|
||||
fastify.register(function(app, _, done) {
|
||||
app.get('/users', () => {})
|
||||
app.route(route)
|
||||
|
||||
done()
|
||||
}, { prefix: '/v1' }) // global route prefix
|
||||
|
||||
await fastify.listen({ port: 0 })
|
||||
```
|
||||
|
||||
### Route Prefixing and fastify-plugin
|
||||
<a id="fastify-plugin"></a>
|
||||
|
||||
Be aware that if you use
|
||||
[`fastify-plugin`](https://github.com/fastify/fastify-plugin) for wrapping your
|
||||
routes, this option will not work. You can still make it work by wrapping a
|
||||
plugin in a plugin, e. g.:
|
||||
```js
|
||||
const fp = require('fastify-plugin')
|
||||
const routes = require('./lib/routes')
|
||||
|
||||
module.exports = fp(async function (app, opts) {
|
||||
app.register(routes, {
|
||||
prefix: '/v1',
|
||||
})
|
||||
}, {
|
||||
name: 'my-routes'
|
||||
})
|
||||
```
|
||||
|
||||
#### Handling of / route inside prefixed plugins
|
||||
|
||||
The `/` route has different behavior depending on if the prefix ends with `/` or
|
||||
not. As an example, if we consider a prefix `/something/`, adding a `/` route
|
||||
will only match `/something/`. If we consider a prefix `/something`, adding a
|
||||
`/` route will match both `/something` and `/something/`.
|
||||
|
||||
See the `prefixTrailingSlash` route option above to change this behavior.
|
||||
|
||||
### Custom Log Level
|
||||
<a id="custom-log-level"></a>
|
||||
|
||||
You might need different log levels in your routes; Fastify achieves this in a
|
||||
very straightforward way.
|
||||
|
||||
You just need to pass the option `logLevel` to the plugin option or the route
|
||||
option with the
|
||||
[value](https://github.com/pinojs/pino/blob/master/docs/api.md#level-string)
|
||||
that you need.
|
||||
|
||||
Be aware that if you set the `logLevel` at plugin level, also the
|
||||
[`setNotFoundHandler`](./Server.md#setnotfoundhandler) and
|
||||
[`setErrorHandler`](./Server.md#seterrorhandler) will be affected.
|
||||
|
||||
```js
|
||||
// server.js
|
||||
const fastify = require('fastify')({ logger: true })
|
||||
|
||||
fastify.register(require('./routes/user'), { logLevel: 'warn' })
|
||||
fastify.register(require('./routes/events'), { logLevel: 'debug' })
|
||||
|
||||
fastify.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
Or you can directly pass it to a route:
|
||||
```js
|
||||
fastify.get('/', { logLevel: 'warn' }, (request, reply) => {
|
||||
reply.send({ hello: 'world' })
|
||||
})
|
||||
```
|
||||
*Remember that the custom log level is applied only to the routes, and not to
|
||||
the global Fastify Logger, accessible with `fastify.log`*
|
||||
|
||||
### Custom Log Serializer
|
||||
<a id="custom-log-serializer"></a>
|
||||
|
||||
In some contexts, you may need to log a large object but it could be a waste of
|
||||
resources for some routes. In this case, you can define custom
|
||||
[`serializers`](https://github.com/pinojs/pino/blob/master/docs/api.md#serializers-object)
|
||||
and attach them in the right context!
|
||||
|
||||
```js
|
||||
const fastify = require('fastify')({ logger: true })
|
||||
|
||||
fastify.register(require('./routes/user'), {
|
||||
logSerializers: {
|
||||
user: (value) => `My serializer one - ${value.name}`
|
||||
}
|
||||
})
|
||||
fastify.register(require('./routes/events'), {
|
||||
logSerializers: {
|
||||
user: (value) => `My serializer two - ${value.name} ${value.surname}`
|
||||
}
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
You can inherit serializers by context:
|
||||
|
||||
```js
|
||||
const fastify = Fastify({
|
||||
logger: {
|
||||
level: 'info',
|
||||
serializers: {
|
||||
user (req) {
|
||||
return {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
headers: req.headers,
|
||||
hostname: req.hostname,
|
||||
remoteAddress: req.ip,
|
||||
remotePort: req.socket.remotePort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
fastify.register(context1, {
|
||||
logSerializers: {
|
||||
user: value => `My serializer father - ${value}`
|
||||
}
|
||||
})
|
||||
|
||||
async function context1 (fastify, opts) {
|
||||
fastify.get('/', (req, reply) => {
|
||||
req.log.info({ user: 'call father serializer', key: 'another key' })
|
||||
// shows: { user: 'My serializer father - call father serializer', key: 'another key' }
|
||||
reply.send({})
|
||||
})
|
||||
}
|
||||
|
||||
fastify.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
### Config
|
||||
<a id="routes-config"></a>
|
||||
|
||||
Registering a new handler, you can pass a configuration object to it and
|
||||
retrieve it in the handler.
|
||||
|
||||
```js
|
||||
// server.js
|
||||
const fastify = require('fastify')()
|
||||
|
||||
function handler (req, reply) {
|
||||
reply.send(reply.context.config.output)
|
||||
}
|
||||
|
||||
fastify.get('/en', { config: { output: 'hello world!' } }, handler)
|
||||
fastify.get('/it', { config: { output: 'ciao mondo!' } }, handler)
|
||||
|
||||
fastify.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
### Constraints
|
||||
<a id="constraints"></a>
|
||||
|
||||
Fastify supports constraining routes to match only certain requests based on
|
||||
some property of the request, like the `Host` header, or any other value via
|
||||
[`find-my-way`](https://github.com/delvedor/find-my-way) constraints.
|
||||
Constraints are specified in the `constraints` property of the route options.
|
||||
Fastify has two built-in constraints ready for use: the `version` constraint and
|
||||
the `host` constraint, and you can add your own custom constraint strategies to
|
||||
inspect other parts of a request to decide if a route should be executed for a
|
||||
request.
|
||||
|
||||
#### Version Constraints
|
||||
|
||||
You can provide a `version` key in the `constraints` option to a route.
|
||||
Versioned routes allow you to declare multiple handlers for the same HTTP route
|
||||
path, which will then be matched according to each request's `Accept-Version`
|
||||
header. The `Accept-Version` header value should follow the
|
||||
[semver](https://semver.org/) specification, and routes should be declared with
|
||||
exact semver versions for matching.
|
||||
|
||||
Fastify will require a request `Accept-Version` header to be set if the route
|
||||
has a version set, and will prefer a versioned route to a non-versioned route
|
||||
for the same path. Advanced version ranges and pre-releases currently are not
|
||||
supported.
|
||||
|
||||
*Be aware that using this feature will cause a degradation of the overall
|
||||
performances of the router.*
|
||||
|
||||
```js
|
||||
fastify.route({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
constraints: { version: '1.2.0' },
|
||||
handler: function (request, reply) {
|
||||
reply.send({ hello: 'world' })
|
||||
}
|
||||
})
|
||||
|
||||
fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
headers: {
|
||||
'Accept-Version': '1.x' // it could also be '1.2.0' or '1.2.x'
|
||||
}
|
||||
}, (err, res) => {
|
||||
// { hello: 'world' }
|
||||
})
|
||||
```
|
||||
|
||||
> ## ⚠ Security Notice
|
||||
> Remember to set a
|
||||
> [`Vary`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary)
|
||||
> header in your responses with the value you are using for defining the
|
||||
> versioning (e.g.: `'Accept-Version'`), to prevent cache poisoning attacks. You
|
||||
> can also configure this as part of your Proxy/CDN.
|
||||
>
|
||||
> ```js
|
||||
> const append = require('vary').append
|
||||
> fastify.addHook('onSend', (req, reply, payload, done) => {
|
||||
> if (req.headers['accept-version']) { // or the custom header you are using
|
||||
> let value = reply.getHeader('Vary') || ''
|
||||
> const header = Array.isArray(value) ? value.join(', ') : String(value)
|
||||
> if ((value = append(header, 'Accept-Version'))) { // or the custom header you are using
|
||||
> reply.header('Vary', value)
|
||||
> }
|
||||
> }
|
||||
> done()
|
||||
> })
|
||||
> ```
|
||||
|
||||
If you declare multiple versions with the same major or minor, Fastify will
|
||||
always choose the highest compatible with the `Accept-Version` header value.
|
||||
|
||||
If the request will not have the `Accept-Version` header, a 404 error will be
|
||||
returned.
|
||||
|
||||
It is possible to define a custom version matching logic. This can be done
|
||||
through the [`constraints`](./Server.md#constraints) configuration when creating
|
||||
a Fastify server instance.
|
||||
|
||||
#### Host Constraints
|
||||
|
||||
You can provide a `host` key in the `constraints` route option for to limit that
|
||||
route to only be matched for certain values of the request `Host` header. `host`
|
||||
constraint values can be specified as strings for exact matches or RegExps for
|
||||
arbitrary host matching.
|
||||
|
||||
```js
|
||||
fastify.route({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
constraints: { host: 'auth.fastify.dev' },
|
||||
handler: function (request, reply) {
|
||||
reply.send('hello world from auth.fastify.dev')
|
||||
}
|
||||
})
|
||||
|
||||
fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
headers: {
|
||||
'Host': 'example.com'
|
||||
}
|
||||
}, (err, res) => {
|
||||
// 404 because the host doesn't match the constraint
|
||||
})
|
||||
|
||||
fastify.inject({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
headers: {
|
||||
'Host': 'auth.fastify.dev'
|
||||
}
|
||||
}, (err, res) => {
|
||||
// => 'hello world from auth.fastify.dev'
|
||||
})
|
||||
```
|
||||
|
||||
RegExp `host` constraints can also be specified allowing constraining to hosts
|
||||
matching wildcard subdomains (or any other pattern):
|
||||
|
||||
```js
|
||||
fastify.route({
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
constraints: { host: /.*\.fastify\.io/ }, // will match any subdomain of fastify.dev
|
||||
handler: function (request, reply) {
|
||||
reply.send('hello world from ' + request.headers.host)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Asynchronous Custom Constraints
|
||||
|
||||
Custom constraints can be provided and the `constraint` criteria can be
|
||||
fetched from another source such as `database`. The use of asynchronous
|
||||
custom constraints should be a last resort as it impacts router
|
||||
performance.
|
||||
|
||||
```js
|
||||
function databaseOperation(field, done) {
|
||||
done(null, field)
|
||||
}
|
||||
|
||||
const secret = {
|
||||
// strategy name for referencing in the route handler `constraints` options
|
||||
name: 'secret',
|
||||
// storage factory for storing routes in the find-my-way route tree
|
||||
storage: function () {
|
||||
let handlers = {}
|
||||
return {
|
||||
get: (type) => { return handlers[type] || null },
|
||||
set: (type, store) => { handlers[type] = store }
|
||||
}
|
||||
},
|
||||
// function to get the value of the constraint from each incoming request
|
||||
deriveConstraint: (req, ctx, done) => {
|
||||
databaseOperation(req.headers['secret'], done)
|
||||
},
|
||||
// optional flag marking if handlers without constraints can match requests that have a value for this constraint
|
||||
mustMatchWhenDerived: true
|
||||
}
|
||||
```
|
||||
|
||||
> ## ⚠ Security Notice
|
||||
> When using with asynchronous constraint. It is highly recommend never return error
|
||||
> inside the callback. If the error is not preventable, it is recommended to provide
|
||||
> a custom `frameworkErrors` handler to deal with it. Otherwise, you route selection
|
||||
> may break or expose sensitive information to attackers.
|
||||
>
|
||||
> ```js
|
||||
> const Fastify = require('fastify')
|
||||
>
|
||||
> const fastify = Fastify({
|
||||
> frameworkErrors: function(err, res, res) {
|
||||
> if(err instanceof Fastify.errorCodes.FST_ERR_ASYNC_CONSTRAINT) {
|
||||
> res.code(400)
|
||||
> return res.send("Invalid header provided")
|
||||
> } else {
|
||||
> res.send(err)
|
||||
> }
|
||||
> }
|
||||
> })
|
||||
> ```
|
||||
|
||||
|
||||
### ⚠ HTTP version check
|
||||
|
||||
Fastify will check the HTTP version of every request, based on configuration
|
||||
options ([http2](./Server.md#http2), [https](./Server.md#https), and
|
||||
[serverFactory](./Server.md#serverfactory)), to determine if it matches one or
|
||||
all of the > following versions: `2.0`, `1.1`, and `1.0`. If Fastify receives a
|
||||
different HTTP version in the request it will return a `505 HTTP Version Not
|
||||
Supported` error.
|
||||
|
||||
| | 2.0 | 1.1 | 1.0 | skip |
|
||||
|:------------------------:|:---:|:---:|:---:|:----:|
|
||||
| http2 | ✓ | | | |
|
||||
| http2 + https | ✓ | | | |
|
||||
| http2 + https.allowHTTP1 | ✓ | ✓ | ✓ | |
|
||||
| https | | ✓ | ✓ | |
|
||||
| http | | ✓ | ✓ | |
|
||||
| serverFactory | | | | ✓ |
|
||||
|
||||
Note: The internal HTTP version check will be removed in the future when Node
|
||||
implements [this feature](https://github.com/nodejs/node/issues/43115).
|
||||
2080
backend/node_modules/fastify/docs/Reference/Server.md
generated
vendored
Normal file
2080
backend/node_modules/fastify/docs/Reference/Server.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
263
backend/node_modules/fastify/docs/Reference/Type-Providers.md
generated
vendored
Normal file
263
backend/node_modules/fastify/docs/Reference/Type-Providers.md
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
## Type Providers
|
||||
|
||||
Type Providers are a TypeScript only feature that enables Fastify to statically
|
||||
infer type information directly from inline JSON Schema. They are an alternative
|
||||
to specifying generic arguments on routes; and can greatly reduce the need to
|
||||
keep associated types for each schema defined in your project.
|
||||
|
||||
### Providers
|
||||
|
||||
Type Providers are offered as additional packages you will need to install into
|
||||
your project. Each provider uses a different inference library under the hood;
|
||||
allowing you to select the library most appropriate for your needs. Official Type
|
||||
Provider packages follow a `@fastify/type-provider-{provider-name}` naming
|
||||
convention, and there are several community ones available as well.
|
||||
|
||||
The following inference packages are supported:
|
||||
|
||||
- [`json-schema-to-ts`](https://github.com/ThomasAribart/json-schema-to-ts)
|
||||
- [`typebox`](https://github.com/sinclairzx81/typebox)
|
||||
- [`zod`](https://github.com/colinhacks/zod)
|
||||
|
||||
See also the Type Provider wrapper packages for each of the packages respectively:
|
||||
|
||||
- [`@fastify/type-provider-json-schema-to-ts`](https://github.com/fastify/fastify-type-provider-json-schema-to-ts)
|
||||
- [`@fastify/type-provider-typebox`](https://github.com/fastify/fastify-type-provider-typebox)
|
||||
- [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod)
|
||||
(3rd party)
|
||||
|
||||
### Json Schema to Ts
|
||||
|
||||
The following sets up a `json-schema-to-ts` Type Provider
|
||||
|
||||
```bash
|
||||
$ npm i @fastify/type-provider-json-schema-to-ts
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { JsonSchemaToTsProvider } from '@fastify/type-provider-json-schema-to-ts'
|
||||
|
||||
import fastify from 'fastify'
|
||||
|
||||
const server = fastify().withTypeProvider<JsonSchemaToTsProvider>()
|
||||
|
||||
server.get('/route', {
|
||||
schema: {
|
||||
querystring: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
foo: { type: 'number' },
|
||||
bar: { type: 'string' },
|
||||
},
|
||||
required: ['foo', 'bar']
|
||||
}
|
||||
}
|
||||
|
||||
}, (request, reply) => {
|
||||
|
||||
// type Query = { foo: number, bar: string }
|
||||
|
||||
const { foo, bar } = request.query // type safe!
|
||||
})
|
||||
```
|
||||
|
||||
### TypeBox
|
||||
|
||||
The following sets up a TypeBox Type Provider
|
||||
|
||||
```bash
|
||||
$ npm i @fastify/type-provider-typebox
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
||||
import { Type } from '@sinclair/typebox'
|
||||
|
||||
import fastify from 'fastify'
|
||||
|
||||
const server = fastify().withTypeProvider<TypeBoxTypeProvider>()
|
||||
|
||||
server.get('/route', {
|
||||
schema: {
|
||||
querystring: Type.Object({
|
||||
foo: Type.Number(),
|
||||
bar: Type.String()
|
||||
})
|
||||
}
|
||||
}, (request, reply) => {
|
||||
|
||||
// type Query = { foo: number, bar: string }
|
||||
|
||||
const { foo, bar } = request.query // type safe!
|
||||
})
|
||||
```
|
||||
|
||||
See also the [TypeBox
|
||||
documentation](https://github.com/sinclairzx81/typebox#validation) on how to set
|
||||
up AJV to work with TypeBox.
|
||||
|
||||
### Zod
|
||||
|
||||
See [official documentation](https://github.com/turkerdev/fastify-type-provider-zod)
|
||||
for Zod type provider instructions.
|
||||
|
||||
|
||||
### Scoped Type-Provider
|
||||
|
||||
The provider types don't propagate globally. In encapsulated usage, one can
|
||||
remap the context to use one or more providers (for example, `typebox` and
|
||||
`json-schema-to-ts` can be used in the same application).
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
import Fastify from 'fastify'
|
||||
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
||||
import { JsonSchemaToTsProvider } from '@fastify/type-provider-json-schema-to-ts'
|
||||
import { Type } from '@sinclair/typebox'
|
||||
|
||||
const fastify = Fastify()
|
||||
|
||||
function pluginWithTypebox(fastify: FastifyInstance, _opts, done): void {
|
||||
fastify.withTypeProvider<TypeBoxTypeProvider>()
|
||||
.get('/', {
|
||||
schema: {
|
||||
body: Type.Object({
|
||||
x: Type.String(),
|
||||
y: Type.Number(),
|
||||
z: Type.Boolean()
|
||||
})
|
||||
}
|
||||
}, (req) => {
|
||||
const { x, y, z } = req.body // type safe
|
||||
});
|
||||
done()
|
||||
}
|
||||
|
||||
function pluginWithJsonSchema(fastify: FastifyInstance, _opts, done): void {
|
||||
fastify.withTypeProvider<JsonSchemaToTsProvider>()
|
||||
.get('/', {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
x: { type: 'string' },
|
||||
y: { type: 'number' },
|
||||
z: { type: 'boolean' }
|
||||
},
|
||||
}
|
||||
}
|
||||
}, (req) => {
|
||||
const { x, y, z } = req.body // type safe
|
||||
});
|
||||
done()
|
||||
}
|
||||
|
||||
fastify.register(pluginWithJsonSchema)
|
||||
fastify.register(pluginWithTypebox)
|
||||
```
|
||||
|
||||
It's also important to mention that once the types don't propagate globally,
|
||||
_currently_ is not possible to avoid multiple registrations on routes when
|
||||
dealing with several scopes, see below:
|
||||
|
||||
```ts
|
||||
import Fastify from 'fastify'
|
||||
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
||||
import { Type } from '@sinclair/typebox'
|
||||
|
||||
const server = Fastify().withTypeProvider<TypeBoxTypeProvider>()
|
||||
|
||||
server.register(plugin1) // wrong
|
||||
server.register(plugin2) // correct
|
||||
|
||||
function plugin1(fastify: FastifyInstance, _opts, done): void {
|
||||
fastify.get('/', {
|
||||
schema: {
|
||||
body: Type.Object({
|
||||
x: Type.String(),
|
||||
y: Type.Number(),
|
||||
z: Type.Boolean()
|
||||
})
|
||||
}
|
||||
}, (req) => {
|
||||
// it doesn't work! in a new scope needs to call `withTypeProvider` again
|
||||
const { x, y, z } = req.body
|
||||
});
|
||||
done()
|
||||
}
|
||||
|
||||
function plugin2(fastify: FastifyInstance, _opts, done): void {
|
||||
const server = fastify.withTypeProvider<TypeBoxTypeProvider>()
|
||||
|
||||
server.get('/', {
|
||||
schema: {
|
||||
body: Type.Object({
|
||||
x: Type.String(),
|
||||
y: Type.Number(),
|
||||
z: Type.Boolean()
|
||||
})
|
||||
}
|
||||
}, (req) => {
|
||||
// works
|
||||
const { x, y, z } = req.body
|
||||
});
|
||||
done()
|
||||
}
|
||||
```
|
||||
|
||||
### Type Definition of FastifyInstance + TypeProvider
|
||||
|
||||
When working with modules one has to make use of `FastifyInstance` with Type
|
||||
Provider generics. See the example below:
|
||||
|
||||
```ts
|
||||
// index.ts
|
||||
import Fastify from 'fastify'
|
||||
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
||||
import { registerRoutes } from './routes'
|
||||
|
||||
const server = Fastify().withTypeProvider<TypeBoxTypeProvider>()
|
||||
|
||||
registerRoutes(server)
|
||||
|
||||
server.listen({ port: 3000 })
|
||||
```
|
||||
|
||||
```ts
|
||||
// routes.ts
|
||||
import { Type } from '@sinclair/typebox'
|
||||
import {
|
||||
FastifyInstance,
|
||||
FastifyBaseLogger,
|
||||
RawReplyDefaultExpression,
|
||||
RawRequestDefaultExpression,
|
||||
RawServerDefault
|
||||
} from 'fastify'
|
||||
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
||||
|
||||
type FastifyTypebox = FastifyInstance<
|
||||
RawServerDefault,
|
||||
RawRequestDefaultExpression<RawServerDefault>,
|
||||
RawReplyDefaultExpression<RawServerDefault>,
|
||||
FastifyBaseLogger,
|
||||
TypeBoxTypeProvider
|
||||
>;
|
||||
|
||||
export function registerRoutes(fastify: FastifyTypebox): void {
|
||||
fastify.get('/', {
|
||||
schema: {
|
||||
body: Type.Object({
|
||||
x: Type.String(),
|
||||
y: Type.Number(),
|
||||
z: Type.Boolean()
|
||||
})
|
||||
}
|
||||
}, (req) => {
|
||||
// works
|
||||
const { x, y, z } = req.body
|
||||
});
|
||||
}
|
||||
```
|
||||
1592
backend/node_modules/fastify/docs/Reference/TypeScript.md
generated
vendored
Normal file
1592
backend/node_modules/fastify/docs/Reference/TypeScript.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1002
backend/node_modules/fastify/docs/Reference/Validation-and-Serialization.md
generated
vendored
Normal file
1002
backend/node_modules/fastify/docs/Reference/Validation-and-Serialization.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
96
backend/node_modules/fastify/docs/Reference/Warnings.md
generated
vendored
Normal file
96
backend/node_modules/fastify/docs/Reference/Warnings.md
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
<h1 align="center">Fastify</h1>
|
||||
|
||||
**Table of contents**
|
||||
- [Warnings](#warnings)
|
||||
- [Warnings In Fastify](#warnings-in-fastify)
|
||||
- [Fastify Warning Codes](#fastify-warning-codes)
|
||||
- [FSTWRN001](#FSTWRN001)
|
||||
- [FSTWRN002](#FSTWRN002)
|
||||
- [Fastify Deprecation Codes](#fastify-deprecation-codes)
|
||||
- [FSTDEP005](#FSTDEP005)
|
||||
- [FSTDEP006](#FSTDEP006)
|
||||
- [FSTDEP007](#FSTDEP007)
|
||||
- [FSTDEP008](#FSTDEP008)
|
||||
- [FSTDEP009](#FSTDEP009)
|
||||
- [FSTDEP010](#FSTDEP010)
|
||||
- [FSTDEP011](#FSTDEP011)
|
||||
- [FSTDEP012](#FSTDEP012)
|
||||
- [FSTDEP013](#FSTDEP013)
|
||||
- [FSTDEP014](#FSTDEP014)
|
||||
- [FSTDEP015](#FSTDEP015)
|
||||
- [FSTDEP016](#FSTDEP016)
|
||||
- [FSTDEP017](#FSTDEP017)
|
||||
- [FSTDEP018](#FSTDEP018)
|
||||
- [FSTDEP019](#FSTDEP019)
|
||||
- [FSTDEP020](#FSTDEP020)
|
||||
- [FSTDEP021](#FSTDEP021)
|
||||
- [FSTDEP022](#FSTDEP022)
|
||||
|
||||
|
||||
## Warnings
|
||||
|
||||
### Warnings In Fastify
|
||||
|
||||
Fastify utilizes Node.js's [warning event](https://nodejs.org/api/process.html#event-warning)
|
||||
API to notify users of deprecated features and known coding mistakes. Fastify's
|
||||
warnings are recognizable by the `FSTWRN` and `FSTDEP` prefixes on warning
|
||||
code. When encountering such a warning, it is highly recommended that the
|
||||
cause of the warning be determined through use of the
|
||||
[`--trace-warnings`](https://nodejs.org/api/cli.html#--trace-warnings) and
|
||||
[`--trace-deprecation`](https://nodejs.org/api/cli.html#--trace-deprecation)
|
||||
flags. These will produce stack traces pointing out where the issue occurs
|
||||
in the application's code. Issues opened about warnings without including
|
||||
this information may be closed due to lack of information.
|
||||
|
||||
In addition to tracing, warnings can also be disabled. It is not recommended to
|
||||
disable warnings as a matter of course, but if necessary, they can be disabled
|
||||
by using any of the following methods:
|
||||
|
||||
- setting the `NODE_NO_WARNINGS` environment variable to `1`
|
||||
- passing the `--no-warnings` flag to the node process
|
||||
- setting 'no-warnings' in the `NODE_OPTIONS` environment variable
|
||||
|
||||
For more information on how to disable warnings, see [node's documentation](https://nodejs.org/api/cli.html).
|
||||
|
||||
However, disabling warnings is not recommended as it may cause
|
||||
potential problems when upgrading Fastify versions.
|
||||
Only experienced users should consider disabling warnings.
|
||||
|
||||
### Fastify Warning Codes
|
||||
|
||||
| Code | Description | How to solve | Discussion |
|
||||
| ---- | ----------- | ------------ | ---------- |
|
||||
| <a id="FSTWRN001">FSTWRN001</a> | The specified schema for a route is missing. This may indicate the schema is not well specified. | Check the schema for the route. | [#4647](https://github.com/fastify/fastify/pull/4647) |
|
||||
| <a id="FSTWRN002">FSTWRN002</a> | The %s plugin being registered mixes async and callback styles, which will result in an error in `fastify@5`. | Do not mix async and callback style. | [#5139](https://github.com/fastify/fastify/pull/5139) |
|
||||
|
||||
|
||||
### Fastify Deprecation Codes
|
||||
|
||||
Deprecation codes are further supported by the Node.js CLI options:
|
||||
|
||||
- [--no-deprecation](https://nodejs.org/api/cli.html#--no-deprecation)
|
||||
- [--throw-deprecation](https://nodejs.org/api/cli.html#--throw-deprecation)
|
||||
- [--trace-deprecation](https://nodejs.org/api/cli.html#--trace-deprecation)
|
||||
|
||||
|
||||
| Code | Description | How to solve | Discussion |
|
||||
| ---- | ----------- | ------------ | ---------- |
|
||||
| <a id="FSTDEP005">FSTDEP005</a> | You are accessing the deprecated `request.connection` property. | Use `request.socket`. | [#2594](https://github.com/fastify/fastify/pull/2594) |
|
||||
| <a id="FSTDEP006">FSTDEP006</a> | You are decorating Request/Reply with a reference type. This reference is shared amongst all requests. | Do not use Arrays/Objects as values when decorating Request/Reply. | [#2688](https://github.com/fastify/fastify/pull/2688) |
|
||||
| <a id="FSTDEP007">FSTDEP007</a> | You are trying to set a HEAD route using `exposeHeadRoute` route flag when a sibling route is already set. | Remove `exposeHeadRoutes` or explicitly set `exposeHeadRoutes` to `false` | [#2700](https://github.com/fastify/fastify/pull/2700) |
|
||||
| <a id="FSTDEP008">FSTDEP008</a> | You are using route constraints via the route `{version: "..."}` option. | Use `{constraints: {version: "..."}}` option. | [#2682](https://github.com/fastify/fastify/pull/2682) |
|
||||
| <a id="FSTDEP009">FSTDEP009</a> | You are using a custom route versioning strategy via the server `{versioning: "..."}` option. | Use `{constraints: {version: "..."}}` option. | [#2682](https://github.com/fastify/fastify/pull/2682) |
|
||||
| <a id="FSTDEP010">FSTDEP010</a> | Modifying the `reply.sent` property is deprecated. | Use the `reply.hijack()` method. | [#3140](https://github.com/fastify/fastify/pull/3140) |
|
||||
| <a id="FSTDEP011">FSTDEP011</a> | Variadic listen method is deprecated. | Use `.listen(optionsObject)`. | [#3712](https://github.com/fastify/fastify/pull/3712) |
|
||||
| <a id="FSTDEP012">FSTDEP012</a> | You are trying to access the deprecated `request.context` property. | Use `request.routeOptions.config` or `request.routeOptions.schema`. | [#4216](https://github.com/fastify/fastify/pull/4216) [#5084](https://github.com/fastify/fastify/pull/5084) |
|
||||
| <a id="FSTDEP013">FSTDEP013</a> | Direct return of "trailers" function is deprecated. | Use "callback" or "async-await" for return value. | [#4380](https://github.com/fastify/fastify/pull/4380) |
|
||||
| <a id="FSTDEP014">FSTDEP014</a> | You are trying to set/access the default route. This property is deprecated. | Use `setNotFoundHandler` if you want to custom a 404 handler or the wildcard (`*`) to match all routes. | [#4480](https://github.com/fastify/fastify/pull/4480) |
|
||||
| <a id="FSTDEP015">FSTDEP015</a> | You are accessing the deprecated `request.routeSchema` property. | Use `request.routeOptions.schema`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
|
||||
| <a id="FSTDEP016">FSTDEP016</a> | You are accessing the deprecated `request.routeConfig` property. | Use `request.routeOptions.config`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
|
||||
| <a id="FSTDEP017">FSTDEP017</a> | You are accessing the deprecated `request.routerPath` property. | Use `request.routeOptions.url`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
|
||||
| <a id="FSTDEP018">FSTDEP018</a> | You are accessing the deprecated `request.routerMethod` property. | Use `request.routeOptions.method`. | [#4470](https://github.com/fastify/fastify/pull/4470) |
|
||||
| <a id="FSTDEP019">FSTDEP019</a> | You are accessing the deprecated `reply.context` property. | Use `reply.routeOptions.config` or `reply.routeOptions.schema`. | [#5032](https://github.com/fastify/fastify/pull/5032) [#5084](https://github.com/fastify/fastify/pull/5084) |
|
||||
| <a id="FSTDEP020">FSTDEP020</a> | You are using the deprecated `reply.getReponseTime()` method. | Use the `reply.elapsedTime` property instead. | [#5263](https://github.com/fastify/fastify/pull/5263) |
|
||||
| <a id="FSTDEP021">FSTDEP021</a> | The `reply.redirect()` method has a new signature: `reply.redirect(url: string, code?: number)`. It will be enforced in `fastify@v5`'. | [#5483](https://github.com/fastify/fastify/pull/5483) |
|
||||
| <a id="FSTDEP022">FSTDEP022</a> | You are using the deprecated json shorthand schema on route %s. Specify full object schema instead. It will be removed in `fastify@v5` | [#5483](https://github.com/fastify/fastify/pull/0000) |
|
||||
Reference in New Issue
Block a user