Projektstart

This commit is contained in:
2026-01-22 15:49:12 +01:00
parent 7212eb6f7a
commit 57e5f652f8
10637 changed files with 2598792 additions and 64 deletions

View 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)
})
})
```

View 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'
```

View 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:
![Figure 1](../resources/encapsulation_context.svg)
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
View 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
View 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
View 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
View 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
View 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&#39;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/

View 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
View 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.

View 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
View 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
```

View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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) |