fastify 6.0.0-alpha.4 → 6.0.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/SECURITY.md +6 -0
- package/build/build-validation.js +2 -0
- package/docs/Guides/Ecosystem.md +12 -53
- package/docs/Guides/Migration-Guide-V5.md +2 -2
- package/docs/Guides/Serverless.md +33 -10
- package/docs/Reference/Errors.md +13 -2
- package/docs/Reference/Hooks.md +13 -0
- package/docs/Reference/Reply.md +787 -681
- package/docs/Reference/Request.md +308 -104
- package/docs/Reference/Routes.md +6 -2
- package/docs/Reference/Server.md +41 -4
- package/docs/Reference/Validation-and-Serialization.md +48 -1
- package/docs/Reference/Warnings.md +2 -0
- package/fastify.d.ts +1 -0
- package/fastify.js +35 -1
- package/lib/config-validator.js +102 -73
- package/lib/content-type-parser.js +35 -14
- package/lib/content-type.js +4 -4
- package/lib/context.js +2 -1
- package/lib/decorate.js +4 -3
- package/lib/error-handler.js +21 -4
- package/lib/error-status.js +4 -2
- package/lib/errors.js +15 -14
- package/lib/handle-request.js +7 -20
- package/lib/reply.js +18 -13
- package/lib/request.js +12 -7
- package/lib/route.js +40 -7
- package/lib/schemas.js +44 -32
- package/lib/validation.js +67 -10
- package/lib/warnings.js +10 -1
- package/package.json +8 -3
- package/test/child-logger-factory.test.js +25 -0
- package/test/close-disposable.test.js +154 -0
- package/test/constrained-routes.test.js +4 -2
- package/test/content-parser.test.js +99 -0
- package/test/decorator.test.js +29 -0
- package/test/diagnostics-channel/error-status.test.js +35 -2
- package/test/handler-timeout.test.js +224 -0
- package/test/internals/all.test.js +5 -0
- package/test/internals/errors.test.js +19 -20
- package/test/internals/initial-config.test.js +2 -0
- package/test/internals/reply-serialize.test.js +20 -0
- package/test/internals/reply.test.js +30 -1
- package/test/internals/request.test.js +50 -0
- package/test/internals/server.test.js +6 -4
- package/test/reply-error.test.js +82 -0
- package/test/reply-media-type.test.js +57 -0
- package/test/reply-trailers.test.js +159 -1
- package/test/rfc-10008.test.js +6 -9
- package/test/router-compile.test.js +241 -0
- package/test/schema-feature.test.js +1 -1
- package/test/schema-serialization.test.js +120 -7
- package/test/schema-validation.test.js +251 -1
- package/test/types/errors.tst.ts +0 -1
- package/test/types/fastify.tst.ts +9 -0
- package/test/types/instance.tst.ts +1 -1
- package/test/types/route.tst.ts +37 -0
- package/test/types/using.tst.ts +20 -0
- package/test/validation-error-handling.test.js +21 -1
- package/types/errors.d.ts +0 -1
- package/types/instance.d.ts +9 -5
- package/types/route.d.ts +4 -2
|
@@ -1,92 +1,71 @@
|
|
|
1
1
|
<h1 align="center">Fastify</h1>
|
|
2
2
|
|
|
3
3
|
## Request
|
|
4
|
+
- [Introduction](#introduction)
|
|
5
|
+
- [Request](#request-object)
|
|
6
|
+
- [Properties](#properties)
|
|
7
|
+
- [.body](#body)
|
|
8
|
+
- [.query](#query)
|
|
9
|
+
- [.params](#params)
|
|
10
|
+
- [.headers](#headers)
|
|
11
|
+
- [.id](#id)
|
|
12
|
+
- [.log](#log)
|
|
13
|
+
- [.method](#method)
|
|
14
|
+
- [.url](#url)
|
|
15
|
+
- [.routeOptions](#routeoptions)
|
|
16
|
+
- [.server](#server)
|
|
17
|
+
- [.raw](#raw)
|
|
18
|
+
- [.ip](#ip)
|
|
19
|
+
- [.ips](#ips)
|
|
20
|
+
- [.host](#host)
|
|
21
|
+
- [.hostname](#hostname)
|
|
22
|
+
- [.port](#port)
|
|
23
|
+
- [.protocol](#protocol)
|
|
24
|
+
- [.originalUrl](#originalurl)
|
|
25
|
+
- [.mediaType](#mediatype)
|
|
26
|
+
- [.signal](#signal)
|
|
27
|
+
- [.socket](#socket)
|
|
28
|
+
- [.is404](#is404)
|
|
29
|
+
- [.validationError](#validationerror)
|
|
30
|
+
- [Methods](#methods)
|
|
31
|
+
- [.getDecorator(name)](#getdecorator)
|
|
32
|
+
- [.setDecorator(name, value)](#setdecorator)
|
|
33
|
+
- [.getValidationFunction(schema | httpPart)](#getvalidationfunction)
|
|
34
|
+
- [.compileValidationSchema(schema, [httpPart])](#compilevalidationschema)
|
|
35
|
+
- [.validateInput(data, [schema | httpPart], [httpPart])](#validate)
|
|
36
|
+
|
|
37
|
+
### Introduction
|
|
38
|
+
<a id="introduction"></a>
|
|
39
|
+
|
|
4
40
|
The first parameter of the handler function is `Request`.
|
|
5
41
|
|
|
6
42
|
Request is a core Fastify object containing the following fields:
|
|
7
|
-
- `query` - The parsed querystring
|
|
8
|
-
|
|
9
|
-
- `
|
|
10
|
-
for details on what request payloads Fastify natively parses and how to support
|
|
11
|
-
other content types.
|
|
12
|
-
- `params` - The params matching the URL. Values are percent-decoded
|
|
13
|
-
(for example `%20` becomes a space, and `%2f` becomes `/`). Decoded
|
|
14
|
-
values may contain `.`, `..`, `/`, or other characters; treat them as
|
|
15
|
-
untrusted input. See the security note below and
|
|
16
|
-
[Routes - Url building](./Routes.md#url-building).
|
|
43
|
+
- `query` - The parsed querystring.
|
|
44
|
+
- `body` - The request payload.
|
|
45
|
+
- `params` - The params matching the URL.
|
|
17
46
|
- [`headers`](#headers) - The headers getter and setter.
|
|
18
47
|
- `raw` - The incoming HTTP request from Node core.
|
|
19
|
-
- `server` - The Fastify server instance
|
|
20
|
-
[encapsulation context](./Encapsulation.md).
|
|
48
|
+
- `server` - The Fastify server instance.
|
|
21
49
|
- `id` - The request ID.
|
|
22
50
|
- `log` - The logger instance of the incoming request.
|
|
23
|
-
- `ip` - The IP address of the incoming request.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
- `ips` - An array of IP addresses, ordered from closest to furthest, from
|
|
27
|
-
`X-Forwarded-For` (only when
|
|
28
|
-
[`trustProxy`](./Server.md#factory-trust-proxy) is enabled).
|
|
29
|
-
- `host` - The host of the incoming request (derived from `X-Forwarded-Host`
|
|
30
|
-
when [`trustProxy`](./Server.md#factory-trust-proxy) is enabled). For HTTP/2
|
|
31
|
-
compatibility, it returns `:authority` if no host header exists. The host
|
|
32
|
-
header may return an empty string if `requireHostHeader` is `false`, not
|
|
33
|
-
provided with HTTP/1.0, or removed by schema validation.
|
|
51
|
+
- `ip` - The IP address of the incoming request.
|
|
52
|
+
- `ips` - An array of IP addresses from `X-Forwarded-For`.
|
|
53
|
+
- `host` - The host of the incoming request.
|
|
34
54
|
- `hostname` - The hostname parsed from `request.host`.
|
|
35
|
-
- `port` - The port parsed from `request.host
|
|
36
|
-
|
|
37
|
-
- `protocol` - The protocol of the incoming request (`https` or `http`). This
|
|
38
|
-
value comes from `socket.encrypted` (or `X-Forwarded-Proto` when
|
|
39
|
-
[`trustProxy`](./Server.md#factory-trust-proxy) is enabled).
|
|
40
|
-
|
|
41
|
-
> ⚠️ Security:
|
|
42
|
-
> `request.params`, `request.query`, `request.headers`, and `request.body`
|
|
43
|
-
> are untrusted network input. Route parameter values are percent-decoded
|
|
44
|
-
> before your handler runs, so a segment like `..%2ffile` becomes `../file`
|
|
45
|
-
> in `request.params`. Do not use parameter values as filesystem paths,
|
|
46
|
-
> template names, or redirect targets without validating or containing
|
|
47
|
-
> them. Prefer [`@fastify/static`](https://github.com/fastify/fastify-static)
|
|
48
|
-
> (or `reply.sendFile`) when serving files from a root directory.
|
|
49
|
-
>
|
|
50
|
-
> `request.ip`, `request.ips`, `request.host`, `request.hostname`,
|
|
51
|
-
> `request.port`, and `request.protocol` come from request metadata
|
|
52
|
-
> (socket and/or forwarding headers) and should also be treated as
|
|
53
|
-
> untrusted input. Fastify does not perform security validation for
|
|
54
|
-
> business logic. If these values are used in security-sensitive decisions,
|
|
55
|
-
> they must be validated explicitly (for example: trusted proxy
|
|
56
|
-
> configuration, allow-lists, strict parsing, and normalization).
|
|
57
|
-
|
|
55
|
+
- `port` - The port parsed from `request.host`.
|
|
56
|
+
- `protocol` - The protocol of the incoming request (`https` or `http`).
|
|
58
57
|
- `method` - The method of the incoming request.
|
|
59
58
|
- `url` - The URL of the incoming request.
|
|
60
|
-
- `originalUrl` -
|
|
61
|
-
|
|
62
|
-
- `mediaType` - The media type extracted from `Content-Type` header. When `Content-Type`
|
|
63
|
-
header is missing, it will return `undefined`.
|
|
59
|
+
- `originalUrl` - The original URL of the incoming request.
|
|
60
|
+
- `mediaType` - The media type extracted from `Content-Type` header.
|
|
64
61
|
- `is404` - `true` if request is being handled by 404 handler, `false` otherwise.
|
|
65
62
|
- `socket` - The underlying connection of the incoming request.
|
|
66
|
-
- `signal` - An `AbortSignal` that aborts
|
|
67
|
-
|
|
68
|
-
there is zero overhead when not used. When
|
|
69
|
-
[`handlerTimeout`](./Server.md#factory-handler-timeout) is configured,
|
|
70
|
-
the signal is pre-created and also aborts on timeout. Pass it to
|
|
71
|
-
`fetch()`, database queries, or any API accepting a `signal` option
|
|
72
|
-
for cooperative cancellation. On timeout, `signal.reason` is the
|
|
73
|
-
`FST_ERR_HANDLER_TIMEOUT` error; on client disconnect it is a generic
|
|
74
|
-
`AbortError`. Check `signal.reason.code` to distinguish the two cases.
|
|
63
|
+
- `signal` - An `AbortSignal` that aborts on handler timeout or client
|
|
64
|
+
disconnect.
|
|
75
65
|
- `routeOptions` - The route [`option`](./Routes.md#routes-options) object.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
- `method` - The HTTP method for the route.
|
|
80
|
-
- `url` - The path of the URL to match this route.
|
|
81
|
-
- `handler` - The handler for this route.
|
|
82
|
-
- `attachValidation` - Attach `validationError` to request (if there is
|
|
83
|
-
a schema defined).
|
|
84
|
-
- `logLevel` - Log level defined for this route.
|
|
85
|
-
- `schema` - The JSON schemas definition for this route.
|
|
86
|
-
- `version` - A semver compatible string that defines the version of the endpoint.
|
|
87
|
-
- `exposeHeadRoute` - Creates a sibling HEAD route for any GET routes.
|
|
88
|
-
- `prefixTrailingSlash` - String used to determine how to handle passing `/`
|
|
89
|
-
as a route with a prefix.
|
|
66
|
+
- `validationError` - The validation error, when `attachValidation` is set.
|
|
67
|
+
- `getDecorator(name)` - Returns the value of a request decorator.
|
|
68
|
+
- `setDecorator(name, value)` - Sets the value of a request decorator.
|
|
90
69
|
- [.getValidationFunction(schema | httpPart)](#getvalidationfunction) -
|
|
91
70
|
Returns a validation function for the specified schema or HTTP part, if
|
|
92
71
|
set or cached.
|
|
@@ -99,29 +78,6 @@ Request is a core Fastify object containing the following fields:
|
|
|
99
78
|
`true` if the input is valid, `false` otherwise. If `httpPart` is provided,
|
|
100
79
|
the function uses the validator for that HTTP part. Defaults to `null`.
|
|
101
80
|
|
|
102
|
-
### Headers
|
|
103
|
-
|
|
104
|
-
The `request.headers` is a getter that returns an object with the headers of the
|
|
105
|
-
incoming request. Set custom headers as follows:
|
|
106
|
-
|
|
107
|
-
```js
|
|
108
|
-
request.headers = {
|
|
109
|
-
'foo': 'bar',
|
|
110
|
-
'baz': 'qux'
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
This operation adds new values to the request headers, accessible via
|
|
115
|
-
`request.headers.bar`. Standard request headers remain accessible via
|
|
116
|
-
`request.raw.headers`.
|
|
117
|
-
|
|
118
|
-
For performance reasons, `Symbol('fastify.RequestAcceptVersion')` may be added
|
|
119
|
-
to headers on `not found` routes.
|
|
120
|
-
|
|
121
|
-
> ℹ️ Note:
|
|
122
|
-
> Schema validation may mutate the `request.headers` and
|
|
123
|
-
> `request.raw.headers` objects, causing the headers to become empty.
|
|
124
|
-
|
|
125
81
|
```js
|
|
126
82
|
fastify.post('/:params', options, function (request, reply) {
|
|
127
83
|
console.log(request.body)
|
|
@@ -151,12 +107,260 @@ fastify.post('/:params', options, function (request, reply) {
|
|
|
151
107
|
request.log.info('some info')
|
|
152
108
|
})
|
|
153
109
|
```
|
|
154
|
-
|
|
110
|
+
|
|
111
|
+
> ⚠️ Security:
|
|
112
|
+
> `request.params`, `request.query`, `request.headers`, and `request.body`
|
|
113
|
+
> are untrusted network input. Route parameter values are percent-decoded
|
|
114
|
+
> before your handler runs, so a segment like `..%2ffile` becomes `../file`
|
|
115
|
+
> in `request.params`. Do not use parameter values as filesystem paths,
|
|
116
|
+
> template names, or redirect targets without validating or containing
|
|
117
|
+
> them. Prefer [`@fastify/static`](https://github.com/fastify/fastify-static)
|
|
118
|
+
> (or `reply.sendFile`) when serving files from a root directory.
|
|
119
|
+
>
|
|
120
|
+
> `request.ip`, `request.ips`, `request.host`, `request.hostname`,
|
|
121
|
+
> `request.port`, and `request.protocol` come from request metadata
|
|
122
|
+
> (socket and/or forwarding headers) and should also be treated as
|
|
123
|
+
> untrusted input. Fastify does not perform security validation for
|
|
124
|
+
> business logic. If these values are used in security-sensitive decisions,
|
|
125
|
+
> they must be validated explicitly (for example: trusted proxy
|
|
126
|
+
> configuration, allow-lists, strict parsing, and normalization).
|
|
127
|
+
|
|
128
|
+
### Request
|
|
129
|
+
<a id="request-object"></a>
|
|
130
|
+
|
|
131
|
+
#### Properties
|
|
132
|
+
<a id="properties"></a>
|
|
133
|
+
|
|
134
|
+
##### .body
|
|
135
|
+
|
|
136
|
+
The request payload. See [Content-Type Parser](./ContentTypeParser.md) for
|
|
137
|
+
details on what request payloads Fastify natively parses and how to support
|
|
138
|
+
other content types.
|
|
139
|
+
|
|
140
|
+
##### .query
|
|
141
|
+
|
|
142
|
+
The parsed querystring. Its format is specified by
|
|
143
|
+
[`querystringParser`](./Server.md#querystringparser).
|
|
144
|
+
|
|
145
|
+
##### .params
|
|
146
|
+
|
|
147
|
+
The params matching the URL. Values are percent-decoded (for example `%20`
|
|
148
|
+
becomes a space, and `%2f` becomes `/`). Decoded values may contain `.`, `..`,
|
|
149
|
+
`/`, or other characters; treat them as untrusted input. See the
|
|
150
|
+
[security note](#introduction) and
|
|
151
|
+
[Routes - Url building](./Routes.md#url-building).
|
|
152
|
+
|
|
153
|
+
##### .headers
|
|
154
|
+
|
|
155
|
+
The `request.headers` is a getter that returns an object with the headers of the
|
|
156
|
+
incoming request. Set custom headers as follows:
|
|
157
|
+
|
|
158
|
+
```js
|
|
159
|
+
request.headers = {
|
|
160
|
+
'foo': 'bar',
|
|
161
|
+
'baz': 'qux'
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
This operation adds new values to the request headers, accessible via
|
|
166
|
+
`request.headers.foo`. Standard request headers remain accessible via
|
|
167
|
+
`request.raw.headers`.
|
|
168
|
+
|
|
169
|
+
For performance reasons, `Symbol('fastify.RequestAcceptVersion')` may be added
|
|
170
|
+
to headers on `not found` routes.
|
|
171
|
+
|
|
172
|
+
> ℹ️ Note:
|
|
173
|
+
> Schema validation may mutate the `request.headers` and
|
|
174
|
+
> `request.raw.headers` objects, causing the headers to become empty.
|
|
175
|
+
|
|
176
|
+
> ℹ️ Note:
|
|
177
|
+
> The setter is additive, so it cannot be used to *remove* a header, and a
|
|
178
|
+
> `headers` schema validator's synchronous `{ value }` result is applied through
|
|
179
|
+
> this same setter. `request.headers` is therefore the incoming request's
|
|
180
|
+
> headers (plus any additive values), not a sanitized or authoritative view. If
|
|
181
|
+
> your application needs an allow-listed header subset, build and consume it
|
|
182
|
+
> explicitly from the validated data or from `request.raw.headers`.
|
|
183
|
+
|
|
184
|
+
##### .id
|
|
185
|
+
|
|
186
|
+
The request ID. It is generated by [`genReqId`](./Server.md#genreqid), or read
|
|
187
|
+
from the header configured with [`requestIdHeader`](./Server.md#requestidheader)
|
|
188
|
+
when the incoming request includes it.
|
|
189
|
+
|
|
190
|
+
##### .log
|
|
191
|
+
|
|
192
|
+
The logger instance of the incoming request. By default, it is a child logger of
|
|
193
|
+
the server logger that adds the request ID (`reqId`) to every log line. See
|
|
194
|
+
[`childLoggerFactory`](./Server.md#childLoggerFactory) to customize it.
|
|
195
|
+
|
|
196
|
+
##### .method
|
|
197
|
+
|
|
198
|
+
The method of the incoming request.
|
|
199
|
+
|
|
200
|
+
##### .url
|
|
201
|
+
|
|
202
|
+
The URL of the incoming request.
|
|
203
|
+
|
|
204
|
+
##### .routeOptions
|
|
205
|
+
|
|
206
|
+
The route [`option`](./Routes.md#routes-options) object.
|
|
207
|
+
- `bodyLimit` - Either server limit or route limit.
|
|
208
|
+
- `handlerTimeout` - The handler timeout configured for this route.
|
|
209
|
+
- `config` - The [`config`](./Routes.md#routes-config) object for this route.
|
|
210
|
+
- `method` - The HTTP method for the route.
|
|
211
|
+
- `url` - The path of the URL to match this route.
|
|
212
|
+
- `handler` - The handler for this route.
|
|
213
|
+
- `attachValidation` - Attach `validationError` to request (if there is
|
|
214
|
+
a schema defined).
|
|
215
|
+
- `logLevel` - Log level defined for this route.
|
|
216
|
+
- `schema` - The JSON schemas definition for this route.
|
|
217
|
+
- `version` - A semver compatible string that defines the version of the
|
|
218
|
+
endpoint.
|
|
219
|
+
- `exposeHeadRoute` - Creates a sibling HEAD route for any GET routes.
|
|
220
|
+
- `prefixTrailingSlash` - String used to determine how to handle passing `/`
|
|
221
|
+
as a route with a prefix.
|
|
222
|
+
|
|
223
|
+
##### .server
|
|
224
|
+
|
|
225
|
+
The Fastify server instance, scoped to the current
|
|
226
|
+
[encapsulation context](./Encapsulation.md).
|
|
227
|
+
|
|
228
|
+
##### .raw
|
|
229
|
+
|
|
230
|
+
The incoming HTTP request from Node core.
|
|
231
|
+
|
|
232
|
+
##### .ip
|
|
233
|
+
|
|
234
|
+
The IP address of the incoming request. This value is taken from
|
|
235
|
+
`socket.remoteAddress` (or from `X-Forwarded-For` when
|
|
236
|
+
[`trustProxy`](./Server.md#factory-trust-proxy) is enabled). It is `undefined`
|
|
237
|
+
when the underlying socket is not available.
|
|
238
|
+
|
|
239
|
+
##### .ips
|
|
240
|
+
|
|
241
|
+
An array of IP addresses, ordered from closest to furthest, from
|
|
242
|
+
`X-Forwarded-For` (only when [`trustProxy`](./Server.md#factory-trust-proxy) is
|
|
243
|
+
enabled). It is `undefined` when `trustProxy` is not enabled.
|
|
244
|
+
|
|
245
|
+
##### .host
|
|
246
|
+
|
|
247
|
+
The host of the incoming request (derived from `X-Forwarded-Host` when
|
|
248
|
+
[`trustProxy`](./Server.md#factory-trust-proxy) is enabled). For HTTP/2
|
|
249
|
+
compatibility, it returns `:authority` if no host header exists. The host header
|
|
250
|
+
may return an empty string if `requireHostHeader` is `false`, not provided with
|
|
251
|
+
HTTP/1.0, or removed by schema validation.
|
|
252
|
+
|
|
253
|
+
##### .hostname
|
|
254
|
+
|
|
255
|
+
The hostname parsed from `request.host`. For IPv6 hosts, the brackets are kept
|
|
256
|
+
(for example, `[::1]`).
|
|
257
|
+
|
|
258
|
+
##### .port
|
|
259
|
+
|
|
260
|
+
The port parsed from `request.host`, which may refer to the port the server is
|
|
261
|
+
listening on. It is `null` when the host does not include a port.
|
|
262
|
+
|
|
263
|
+
##### .protocol
|
|
264
|
+
|
|
265
|
+
The protocol of the incoming request (`https` or `http`). This value comes from
|
|
266
|
+
`socket.encrypted` (or `X-Forwarded-Proto` when
|
|
267
|
+
[`trustProxy`](./Server.md#factory-trust-proxy) is enabled). It is `undefined`
|
|
268
|
+
when the underlying socket is not available.
|
|
269
|
+
|
|
270
|
+
##### .originalUrl
|
|
271
|
+
|
|
272
|
+
Similar to `url`, allows access to the original `url` in case of internal
|
|
273
|
+
re-routing.
|
|
274
|
+
|
|
275
|
+
##### .mediaType
|
|
276
|
+
|
|
277
|
+
The media type extracted from `Content-Type` header. When `Content-Type` header
|
|
278
|
+
is missing, it will return `undefined`.
|
|
279
|
+
|
|
280
|
+
##### .signal
|
|
281
|
+
|
|
282
|
+
An `AbortSignal` that aborts when the handler timeout fires or the client
|
|
283
|
+
disconnects. Created lazily on first access, so there is zero overhead when not
|
|
284
|
+
used. When [`handlerTimeout`](./Server.md#factory-handler-timeout) is
|
|
285
|
+
configured, the signal is pre-created and also aborts on timeout. Pass it to
|
|
286
|
+
`fetch()`, database queries, or any API accepting a `signal` option for
|
|
287
|
+
cooperative cancellation. On timeout, `signal.reason` is the
|
|
288
|
+
`FST_ERR_HANDLER_TIMEOUT` error; on client disconnect it is a generic
|
|
289
|
+
`AbortError`. Check `signal.reason.code` to distinguish the two cases.
|
|
290
|
+
|
|
291
|
+
##### .socket
|
|
292
|
+
|
|
293
|
+
The underlying connection of the incoming request.
|
|
294
|
+
|
|
295
|
+
##### .is404
|
|
296
|
+
|
|
297
|
+
`true` if request is being handled by 404 handler, `false` otherwise.
|
|
298
|
+
|
|
299
|
+
##### .validationError
|
|
300
|
+
|
|
301
|
+
The validation error of the request. It is set only when the route has the
|
|
302
|
+
[`attachValidation`](./Routes.md#routes-options) option enabled and the
|
|
303
|
+
validation fails; otherwise it is `undefined`. In that case, Fastify calls the
|
|
304
|
+
handler instead of replying with a `400` error. See
|
|
305
|
+
[Validation and Serialization](./Validation-and-Serialization.md#error-handling)
|
|
306
|
+
for the properties of the error object.
|
|
307
|
+
|
|
308
|
+
```js
|
|
309
|
+
fastify.post('/', { schema, attachValidation: true }, function (request, reply) {
|
|
310
|
+
if (request.validationError) {
|
|
311
|
+
// `request.validationError.validationContext` is the failed part,
|
|
312
|
+
// for example `body`
|
|
313
|
+
reply.code(422).send(request.validationError)
|
|
314
|
+
return
|
|
315
|
+
}
|
|
316
|
+
reply.send({ hello: 'world' })
|
|
317
|
+
})
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Methods
|
|
321
|
+
<a id="methods"></a>
|
|
322
|
+
|
|
323
|
+
##### .getDecorator(name)
|
|
324
|
+
<a id="getdecorator"></a>
|
|
325
|
+
|
|
326
|
+
Returns the value of a request decorator declared with
|
|
327
|
+
[`decorateRequest`](./Decorators.md#decoraterequestname-value-dependencies).
|
|
328
|
+
If the decorator is a function, it is returned bound to the request. It throws
|
|
329
|
+
an `FST_ERR_DEC_UNDECLARED` error if the decorator has not been declared. See
|
|
330
|
+
[`getDecorator`](./Decorators.md#getdecoratorname) for more details.
|
|
331
|
+
|
|
332
|
+
```js
|
|
333
|
+
fastify.decorateRequest('user', null)
|
|
334
|
+
|
|
335
|
+
fastify.get('/', function (request, reply) {
|
|
336
|
+
const user = request.getDecorator('user')
|
|
337
|
+
reply.send({ user })
|
|
338
|
+
})
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
##### .setDecorator(name, value)
|
|
342
|
+
<a id="setdecorator"></a>
|
|
343
|
+
|
|
344
|
+
Sets the value of a request decorator declared with
|
|
345
|
+
[`decorateRequest`](./Decorators.md#decoraterequestname-value-dependencies).
|
|
346
|
+
It throws an `FST_ERR_DEC_UNDECLARED` error if the decorator has not been
|
|
347
|
+
declared. See [`setDecorator`](./Decorators.md#setdecoratorname-value) for more
|
|
348
|
+
details.
|
|
349
|
+
|
|
350
|
+
```js
|
|
351
|
+
fastify.decorateRequest('user', null)
|
|
352
|
+
|
|
353
|
+
fastify.addHook('preHandler', async (request) => {
|
|
354
|
+
request.setDecorator('user', 'Bob Dylan')
|
|
355
|
+
})
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
##### .getValidationFunction(schema | httpPart)
|
|
155
359
|
<a id="getvalidationfunction"></a>
|
|
156
360
|
|
|
157
361
|
By calling this function with a provided `schema` or `httpPart`, it returns a
|
|
158
362
|
`validation` function to validate diverse inputs. It returns `undefined` if no
|
|
159
|
-
|
|
363
|
+
validation function is found using the provided inputs.
|
|
160
364
|
|
|
161
365
|
This function has an `errors` property. Errors encountered during the last
|
|
162
366
|
validation are assigned to `errors`.
|
|
@@ -182,10 +386,10 @@ console.log(validate({ foo: 0.5 })) // false
|
|
|
182
386
|
console.log(validate.errors) // validation errors
|
|
183
387
|
```
|
|
184
388
|
|
|
185
|
-
See [.compileValidationSchema(schema, [
|
|
389
|
+
See [.compileValidationSchema(schema, [httpPart])](#compilevalidationschema)
|
|
186
390
|
for more information on compiling validation schemas.
|
|
187
391
|
|
|
188
|
-
|
|
392
|
+
##### .compileValidationSchema(schema, [httpPart])
|
|
189
393
|
<a id="compilevalidationschema"></a>
|
|
190
394
|
|
|
191
395
|
This function compiles a validation schema and returns a function to validate data.
|
|
@@ -223,8 +427,8 @@ const validate = request
|
|
|
223
427
|
type: 'string'
|
|
224
428
|
}
|
|
225
429
|
}
|
|
226
|
-
},
|
|
227
|
-
console.log(validate({
|
|
430
|
+
}, 'body')
|
|
431
|
+
console.log(validate({ foo: {} })) // false
|
|
228
432
|
console.log(validate.errors) // validation errors
|
|
229
433
|
```
|
|
230
434
|
|
|
@@ -272,7 +476,7 @@ const newValidate = request.compileValidationSchema(newSchema)
|
|
|
272
476
|
console.log(newValidate === validate) // false
|
|
273
477
|
```
|
|
274
478
|
|
|
275
|
-
|
|
479
|
+
##### .validateInput(data, [schema | httpPart], [httpPart])
|
|
276
480
|
<a id="validate"></a>
|
|
277
481
|
|
|
278
482
|
This function validates the input based on the provided schema or HTTP part. If
|
|
@@ -310,5 +514,5 @@ request
|
|
|
310
514
|
.validateInput({ hello: 'world'}, 'query') // false
|
|
311
515
|
```
|
|
312
516
|
|
|
313
|
-
See [.compileValidationSchema(schema, [
|
|
517
|
+
See [.compileValidationSchema(schema, [httpPart])](#compilevalidationschema)
|
|
314
518
|
for more information on compiling validation schemas.
|
package/docs/Reference/Routes.md
CHANGED
|
@@ -32,7 +32,7 @@ fastify.route(options)
|
|
|
32
32
|
<a id="options"></a>
|
|
33
33
|
|
|
34
34
|
* `method`: currently it supports `GET`, `HEAD`, `TRACE`, `DELETE`,
|
|
35
|
-
`OPTIONS`, `PATCH`, `PUT` and `
|
|
35
|
+
`OPTIONS`, `PATCH`, `PUT`, `POST` and `QUERY`. To accept more methods,
|
|
36
36
|
the [`addHttpMethod`](./Server.md#addHttpMethod) must be used.
|
|
37
37
|
It could also be an array of methods.
|
|
38
38
|
* `url`: the path of the URL to match this route (alias: `path`).
|
|
@@ -41,7 +41,7 @@ fastify.route(options)
|
|
|
41
41
|
[here](./Validation-and-Serialization.md) for more info.
|
|
42
42
|
|
|
43
43
|
* `body`: validates the body of the request if it is a POST, PUT, PATCH,
|
|
44
|
-
TRACE, SEARCH, PROPFIND, PROPPATCH or
|
|
44
|
+
TRACE, SEARCH, PROPFIND, PROPPATCH, LOCK or QUERY method.
|
|
45
45
|
* `querystring` or `query`: validates the querystring. This can be a complete
|
|
46
46
|
JSON Schema object, with the property `type` of `object` and `properties`
|
|
47
47
|
object of parameters, or simply the values of what would be contained in the
|
|
@@ -198,6 +198,10 @@ The above route declaration is more *Hapi*-like, but if you prefer an
|
|
|
198
198
|
|
|
199
199
|
`fastify.patch(path, [options], handler)`
|
|
200
200
|
|
|
201
|
+
`fastify.query(path, [options], handler)`
|
|
202
|
+
|
|
203
|
+
> The `QUERY` method (RFC 10008) requires a `Content-Type` header.
|
|
204
|
+
|
|
201
205
|
Example:
|
|
202
206
|
```js
|
|
203
207
|
const opts = {
|
package/docs/Reference/Server.md
CHANGED
|
@@ -41,6 +41,7 @@ describes the properties available in that options object.
|
|
|
41
41
|
- [`allowUnsafeRegex`](#allowunsaferegex)
|
|
42
42
|
- [`buildPrettyMeta`](#buildprettymeta)
|
|
43
43
|
- [`caseSensitive`](#casesensitive)
|
|
44
|
+
- [`compile`](#compile)
|
|
44
45
|
- [`constraints`](#constraints)
|
|
45
46
|
- [`defaultRoute`](#defaultroute)
|
|
46
47
|
- [`ignoreDuplicateSlashes`](#ignoreduplicateslashes)
|
|
@@ -213,7 +214,7 @@ ignored.
|
|
|
213
214
|
|
|
214
215
|
Defines the maximum number of milliseconds for receiving the entire request from
|
|
215
216
|
the client. See [`server.requestTimeout`
|
|
216
|
-
property](https://nodejs.org/dist/latest/docs/api/http.html#
|
|
217
|
+
property](https://nodejs.org/dist/latest/docs/api/http.html#serverrequesttimeout)
|
|
217
218
|
to understand the effect of this option.
|
|
218
219
|
|
|
219
220
|
When `serverFactory` option is specified, this option is ignored.
|
|
@@ -920,6 +921,36 @@ fastify.get('/user/:username', (request, reply) => {
|
|
|
920
921
|
})
|
|
921
922
|
```
|
|
922
923
|
|
|
924
|
+
### `compile`
|
|
925
|
+
<a id="compile"></a>
|
|
926
|
+
|
|
927
|
+
+ Default: `false`
|
|
928
|
+
|
|
929
|
+
When `true`, Fastify calls the
|
|
930
|
+
[`compile()`](https://github.com/delvedor/find-my-way#compiler-mode) method of
|
|
931
|
+
`find-my-way` once all the routes are registered, right before the
|
|
932
|
+
[`onReady`](./Hooks.md#onready) hooks run. This applies to both the main
|
|
933
|
+
router and the router used for [not found handlers](#set-not-found-handler).
|
|
934
|
+
Each HTTP method's routing tree is
|
|
935
|
+
turned into generated JavaScript instead of being walked for every request,
|
|
936
|
+
which makes route lookups faster. Matching semantics are the same as with the
|
|
937
|
+
default tree walk.
|
|
938
|
+
|
|
939
|
+
```js
|
|
940
|
+
const fastify = require('fastify')({
|
|
941
|
+
routerOptions: {
|
|
942
|
+
compile: true
|
|
943
|
+
}
|
|
944
|
+
})
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
Keep in mind that:
|
|
948
|
+
|
|
949
|
+
+ the compiled matcher works on the raw request URL; URLs containing
|
|
950
|
+
percent-encoded characters fall back to the decoded path and are not faster;
|
|
951
|
+
+ every route generates its own code, so applications with thousands of routes
|
|
952
|
+
produce a large amount of JavaScript, which needs to warm up per route.
|
|
953
|
+
|
|
923
954
|
### `constraints`
|
|
924
955
|
<a id="constraints"></a>
|
|
925
956
|
|
|
@@ -1044,9 +1075,14 @@ multi) routes by using `maxParamLength` option; the default value is 100
|
|
|
1044
1075
|
characters. If the maximum length limit is reached, the not found route will
|
|
1045
1076
|
be invoked.
|
|
1046
1077
|
|
|
1047
|
-
|
|
1048
|
-
against
|
|
1049
|
-
|
|
1078
|
+
For regex routes, the limit applies to the values captured by the regular
|
|
1079
|
+
expression, and it is checked only after the expression has run against the
|
|
1080
|
+
whole path segment. `maxParamLength` therefore does not limit the input a route
|
|
1081
|
+
regex processes and does not protect against [ReDoS
|
|
1082
|
+
attacks](https://community.owasp.org/attacks/Regular_expression_Denial_of_Service_-_ReDoS).
|
|
1083
|
+
To guard against ReDoS, keep [`allowUnsafeRegex`](#allow-unsafe-regex)
|
|
1084
|
+
disabled so that potentially catastrophic regular expressions are rejected when
|
|
1085
|
+
the route is registered.
|
|
1050
1086
|
|
|
1051
1087
|
|
|
1052
1088
|
### `onBadUrl`
|
|
@@ -2382,6 +2418,7 @@ The properties that can currently be exposed are:
|
|
|
2382
2418
|
- allowUnsafeRegex
|
|
2383
2419
|
- buildPrettyMeta
|
|
2384
2420
|
- caseSensitive
|
|
2421
|
+
- compile
|
|
2385
2422
|
- constraints
|
|
2386
2423
|
- defaultRoute
|
|
2387
2424
|
- ignoreDuplicateSlashes
|
|
@@ -167,6 +167,22 @@ parameters at the top level.
|
|
|
167
167
|
> ℹ For using the latest Ajv (v8), refer to the
|
|
168
168
|
> [`schemaController`](./Server.md#schema-controller) section.
|
|
169
169
|
|
|
170
|
+
##### Header name case
|
|
171
|
+
|
|
172
|
+
Node.js exposes request header names in lowercase. Fastify normalizes header
|
|
173
|
+
names in a `headers` schema to lowercase before compilation, so assertions
|
|
174
|
+
written in the canonical header-name case still match the request, for example
|
|
175
|
+
`required: ['X-Api-Key']`, `dependencies`, and a `propertyNames` deny-list that
|
|
176
|
+
uses `enum` or `const`.
|
|
177
|
+
|
|
178
|
+
Regular-expression constraints on header names are the exception. A
|
|
179
|
+
`patternProperties` key and a `propertyNames` `pattern` are regular expressions
|
|
180
|
+
matched against the already-lowercased header names, and Fastify cannot safely
|
|
181
|
+
rewrite a regular expression. Author them to match lowercase (for example
|
|
182
|
+
`^x-debug-.*$`, not `^X-Debug-.*$`) or make them case-insensitive. A pattern
|
|
183
|
+
written in canonical case will not match, and the assertion it guards will not
|
|
184
|
+
apply.
|
|
185
|
+
|
|
170
186
|
Example:
|
|
171
187
|
```js
|
|
172
188
|
const bodyJsonSchema = {
|
|
@@ -639,6 +655,23 @@ an application.
|
|
|
639
655
|
> failure by rejecting (throwing), and it cannot coerce the request part through
|
|
640
656
|
> a resolved `value`.
|
|
641
657
|
|
|
658
|
+
##### `headers` and the `{ value }` result
|
|
659
|
+
|
|
660
|
+
For the `headers` part specifically, the synchronous success `value` is applied
|
|
661
|
+
through the additive [`request.headers`](./Request.md#headers) setter. That
|
|
662
|
+
setter *adds or overrides* headers on top of the raw request headers; it does
|
|
663
|
+
**not** replace them. Raw request headers remain separately available as
|
|
664
|
+
`request.raw.headers`, and any incoming header that is not present in the
|
|
665
|
+
returned `value` is still visible on `request.headers`.
|
|
666
|
+
|
|
667
|
+
Consequently, a synchronous custom `headers` validator cannot remove a header by
|
|
668
|
+
simply omitting it from `value`. The same applies to the default Ajv validator:
|
|
669
|
+
`request.headers` is the incoming request's headers (plus any additive values)
|
|
670
|
+
and is not a sanitized, authoritative view. If your application needs a
|
|
671
|
+
sanitized or allow-listed header view — for example to drive an authorization
|
|
672
|
+
decision — build and consume that view explicitly from the validated data rather
|
|
673
|
+
than re-reading `request.headers`.
|
|
674
|
+
|
|
642
675
|
##### .statusCode property
|
|
643
676
|
|
|
644
677
|
All validation errors have a `.statusCode` property set to `400`, ensuring the
|
|
@@ -766,7 +799,7 @@ For example:
|
|
|
766
799
|
const schema = {
|
|
767
800
|
response: {
|
|
768
801
|
200: {
|
|
769
|
-
description: 'Response schema that support different content types'
|
|
802
|
+
description: 'Response schema that support different content types',
|
|
770
803
|
content: {
|
|
771
804
|
'application/json': {
|
|
772
805
|
schema: {
|
|
@@ -818,6 +851,15 @@ const schema = {
|
|
|
818
851
|
fastify.post('/url', { schema }, handler)
|
|
819
852
|
```
|
|
820
853
|
|
|
854
|
+
> When the route declares a per-content-type response schema through `content`,
|
|
855
|
+
> Fastify matches the response `Content-Type` against the declared keys and falls
|
|
856
|
+
> back to `*/*` (if present). If the response `Content-Type` is not declared and
|
|
857
|
+
> there is no `*/*` key, serialization **fails closed**: Fastify throws
|
|
858
|
+
> `FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN` and replies with a `500` error,
|
|
859
|
+
> instead of silently serializing the payload with `JSON.stringify` (which would
|
|
860
|
+
> bypass the response schema). Every `Content-Type` a route may respond with must
|
|
861
|
+
> be declared, or the route must define a `*/*` catch-all.
|
|
862
|
+
|
|
821
863
|
#### Serializer Compiler
|
|
822
864
|
<a id="schema-serializer"></a>
|
|
823
865
|
|
|
@@ -898,6 +940,11 @@ message has to be rebuilt from the raw validation result:
|
|
|
898
940
|
- `validationContext` is the part of the request that failed validation
|
|
899
941
|
(`body`, `params`, `querystring` or `headers`).
|
|
900
942
|
- `code` is `FST_ERR_VALIDATION` and `statusCode` is `400`.
|
|
943
|
+
- When the validator reports a list of errors (as Ajv does) and the default
|
|
944
|
+
[`schemaErrorFormatter`](#schemaerrorformatter) is used, the error is an
|
|
945
|
+
instance of [`FST_ERR_VALIDATION`](./Errors.md#fst_err_validation) without a
|
|
946
|
+
[stack trace](./Errors.md#errors-in-input-data). Errors returned by the
|
|
947
|
+
validator itself, or by a custom formatter, are used as they are.
|
|
901
948
|
|
|
902
949
|
```js
|
|
903
950
|
const fastify = Fastify()
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
- [Fastify Security Codes](#fastify-security-codes)
|
|
11
11
|
- [FSTSEC001](#FSTSEC001)
|
|
12
12
|
- [FSTSEC002](#FSTSEC002)
|
|
13
|
+
- [FSTSEC003](#FSTSEC003)
|
|
13
14
|
- [Fastify Deprecation Codes](#fastify-deprecation-codes)
|
|
14
15
|
|
|
15
16
|
## Warnings
|
|
@@ -51,6 +52,7 @@ Disabling warnings is not recommended and may cause unexpected behavior.
|
|
|
51
52
|
| ---- | ----------- | ------------ | ---------- |
|
|
52
53
|
| <a id="FSTSEC001">FSTSEC001</a> | A `RegExp` Content-Type is used that may be vulnerable to a CORS bypass, because it does not anchor the essence MIME type. | Start the `RegExp` with `^` or include `;?` so the essence MIME type is detected correctly. | [#4450](https://github.com/fastify/fastify/pull/4450) |
|
|
53
54
|
| <a id="FSTSEC002">FSTSEC002</a> | A headers schema references an external `$ref` (a schema registered with `addSchema`) that is not reached by header case normalization. Header names in the referenced schema keep their original case and do not match the lowercased request headers, so case-insensitive assertions such as `required` and `dependencies` may not apply. | Inline the header schema instead of referencing it with an external `$ref`. | - |
|
|
55
|
+
| <a id="FSTSEC003">FSTSEC003</a> | A headers schema uses a `$ref` inside `propertyNames` that is not reached by header case normalization. Header names held in the referenced schema keep their original case and do not match the lowercased request headers, so a case-insensitive deny-list or allow-list on header names may not apply. | Inline the `propertyNames` constraint instead of referencing it with a `$ref`. | - |
|
|
54
56
|
|
|
55
57
|
### Fastify Deprecation Codes
|
|
56
58
|
|