fastify 5.2.1 → 5.3.0

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.
Files changed (85) hide show
  1. package/LICENSE +1 -1
  2. package/PROJECT_CHARTER.md +7 -7
  3. package/README.md +24 -25
  4. package/SPONSORS.md +1 -0
  5. package/docs/Guides/Benchmarking.md +4 -4
  6. package/docs/Guides/Database.md +1 -1
  7. package/docs/Guides/Delay-Accepting-Requests.md +10 -10
  8. package/docs/Guides/Ecosystem.md +7 -1
  9. package/docs/Guides/Fluent-Schema.md +1 -1
  10. package/docs/Guides/Getting-Started.md +9 -5
  11. package/docs/Guides/Index.md +1 -1
  12. package/docs/Guides/Migration-Guide-V4.md +1 -1
  13. package/docs/Guides/Migration-Guide-V5.md +12 -2
  14. package/docs/Guides/Plugins-Guide.md +6 -6
  15. package/docs/Guides/Serverless.md +14 -48
  16. package/docs/Guides/Style-Guide.md +2 -2
  17. package/docs/Guides/Testing.md +2 -2
  18. package/docs/Guides/Write-Plugin.md +2 -3
  19. package/docs/Reference/ContentTypeParser.md +58 -78
  20. package/docs/Reference/Decorators.md +249 -60
  21. package/docs/Reference/Encapsulation.md +28 -33
  22. package/docs/Reference/Errors.md +52 -53
  23. package/docs/Reference/HTTP2.md +7 -7
  24. package/docs/Reference/Hooks.md +31 -30
  25. package/docs/Reference/LTS.md +10 -15
  26. package/docs/Reference/Lifecycle.md +19 -24
  27. package/docs/Reference/Logging.md +59 -56
  28. package/docs/Reference/Middleware.md +19 -19
  29. package/docs/Reference/Plugins.md +55 -71
  30. package/docs/Reference/Principles.md +25 -30
  31. package/docs/Reference/Reply.md +11 -10
  32. package/docs/Reference/Request.md +89 -98
  33. package/docs/Reference/Routes.md +108 -128
  34. package/docs/Reference/Server.md +18 -16
  35. package/docs/Reference/Type-Providers.md +19 -21
  36. package/docs/Reference/TypeScript.md +1 -18
  37. package/docs/Reference/Validation-and-Serialization.md +134 -159
  38. package/docs/Reference/Warnings.md +22 -25
  39. package/fastify.js +3 -2
  40. package/lib/contentTypeParser.js +7 -8
  41. package/lib/decorate.js +18 -3
  42. package/lib/error-handler.js +14 -12
  43. package/lib/errors.js +4 -0
  44. package/lib/headRoute.js +4 -2
  45. package/lib/pluginUtils.js +4 -2
  46. package/lib/reply.js +17 -2
  47. package/lib/request.js +28 -2
  48. package/lib/server.js +5 -0
  49. package/lib/validation.js +1 -1
  50. package/lib/warnings.js +9 -0
  51. package/lib/wrapThenable.js +8 -1
  52. package/package.json +12 -12
  53. package/test/bundler/esbuild/package.json +1 -1
  54. package/test/close.test.js +125 -108
  55. package/test/custom-parser-async.test.js +34 -36
  56. package/test/custom-parser.4.test.js +55 -38
  57. package/test/decorator.test.js +174 -4
  58. package/test/fastify-instance.test.js +12 -2
  59. package/test/genReqId.test.js +125 -174
  60. package/test/has-route.test.js +1 -3
  61. package/test/hooks.on-listen.test.js +17 -14
  62. package/test/internals/content-type-parser.test.js +1 -1
  63. package/test/internals/errors.test.js +14 -1
  64. package/test/issue-4959.test.js +84 -0
  65. package/test/listen.1.test.js +37 -34
  66. package/test/listen.2.test.js +50 -40
  67. package/test/listen.3.test.js +28 -32
  68. package/test/listen.4.test.js +61 -45
  69. package/test/listen.5.test.js +23 -0
  70. package/test/register.test.js +55 -50
  71. package/test/request-error.test.js +114 -94
  72. package/test/route-shorthand.test.js +36 -32
  73. package/test/stream.5.test.js +35 -33
  74. package/test/throw.test.js +87 -91
  75. package/test/toolkit.js +32 -0
  76. package/test/trust-proxy.test.js +23 -23
  77. package/test/types/instance.test-d.ts +4 -0
  78. package/test/types/reply.test-d.ts +1 -0
  79. package/test/types/request.test-d.ts +4 -0
  80. package/test/types/type-provider.test-d.ts +40 -0
  81. package/test/upgrade.test.js +32 -33
  82. package/types/instance.d.ts +6 -0
  83. package/types/reply.d.ts +1 -0
  84. package/types/request.d.ts +2 -0
  85. package/types/type-provider.d.ts +12 -3
@@ -14,7 +14,7 @@ suggestion"](https://github.com/fastify/fastify/issues?q=is%3Aissue+is%3Aopen+la
14
14
  in our issue tracker!*
15
15
 
16
16
  ## Code
17
- Fastify uses different techniques to optimize its code, many of them are
17
+ Fastify uses different techniques to optimize its code, many of which are
18
18
  documented in our Guides. We highly recommend you read [the hitchhiker's guide
19
19
  to plugins](./Plugins-Guide.md) to discover all the APIs you can use to build
20
20
  your plugin and learn how to use them.
@@ -53,8 +53,7 @@ Always put an example file in your repository. Examples are very helpful for
53
53
  users and give a very fast way to test your plugin. Your users will be grateful.
54
54
 
55
55
  ## Test
56
- It is extremely important that a plugin is thoroughly tested to verify that is
57
- working properly.
56
+ A plugin **must** be thoroughly tested to verify that is working properly.
58
57
 
59
58
  A plugin without tests will not be accepted to the ecosystem list. A lack of
60
59
  tests does not inspire trust nor guarantee that the code will continue to work
@@ -1,38 +1,32 @@
1
1
  <h1 align="center">Fastify</h1>
2
2
 
3
3
  ## `Content-Type` Parser
4
- Natively, Fastify only supports `'application/json'` and `'text/plain'` content
5
- types. If the content type is not one of these, an
6
- `FST_ERR_CTP_INVALID_MEDIA_TYPE` error will be thrown.
7
- Other common content types are supported through the use of
8
- [plugins](https://fastify.dev/ecosystem/).
4
+ Fastify natively supports `'application/json'` and `'text/plain'` content types
5
+ with a default charset of `utf-8`. These default parsers can be changed or
6
+ removed.
9
7
 
10
- The default charset is `utf-8`. If you need to support different content types,
11
- you can use the `addContentTypeParser` API. *The default JSON and/or plain text
12
- parser can be changed or removed.*
8
+ Unsupported content types will throw an `FST_ERR_CTP_INVALID_MEDIA_TYPE` error.
13
9
 
14
- *Note: If you decide to specify your own content type with the `Content-Type`
15
- header, UTF-8 will not be the default. Be sure to include UTF-8 like this
16
- `text/html; charset=utf-8`.*
10
+ To support other content types, use the `addContentTypeParser` API or an
11
+ existing [plugin](https://fastify.dev/ecosystem/).
17
12
 
18
- As with the other APIs, `addContentTypeParser` is encapsulated in the scope in
19
- which it is declared. This means that if you declare it in the root scope it
20
- will be available everywhere, while if you declare it inside a plugin it will be
21
- available only in that scope and its children.
13
+ As with other APIs, `addContentTypeParser` is encapsulated in the scope in which
14
+ it is declared. If declared in the root scope, it is available everywhere; if
15
+ declared in a plugin, it is available only in that scope and its children.
22
16
 
23
17
  Fastify automatically adds the parsed request payload to the [Fastify
24
- request](./Request.md) object which you can access with `request.body`.
25
-
26
- Note that for `GET` and `HEAD` requests the payload is never parsed. For
27
- `OPTIONS` and `DELETE` requests the payload is only parsed if the content type
28
- is given in the content-type header. If it is not given, the
29
- [catch-all](#catch-all) parser is not executed as with `POST`, `PUT` and
30
- `PATCH`, but the payload is simply not parsed.
31
-
32
- > ## Security Notice
33
- > When using with RegExp to detect `Content-Type`, you should beware of
34
- > how to properly detect the `Content-Type`. For example, if you need
35
- > `application/*`, you should use `/^application\/([\w-]+);?/` to match the
18
+ request](./Request.md) object, accessible via `request.body`.
19
+
20
+ Note that for `GET` and `HEAD` requests, the payload is never parsed. For
21
+ `OPTIONS` and `DELETE` requests, the payload is parsed only if a valid
22
+ `content-type` header is provided. Unlike `POST`, `PUT`, and `PATCH`, the
23
+ [catch-all](#catch-all) parser is not executed, and the payload is simply not
24
+ parsed.
25
+
26
+ > ⚠ Warning:
27
+ > When using regular expressions to detect `Content-Type`, it is important to
28
+ > ensure proper detection. For example, to match `application/*`, use
29
+ > `/^application\/([\w-]+);?/` to match the
36
30
  > [essence MIME type](https://mimesniff.spec.whatwg.org/#mime-type-miscellaneous)
37
31
  > only.
38
32
 
@@ -70,11 +64,10 @@ fastify.addContentTypeParser('text/json', { parseAs: 'string' }, fastify.getDefa
70
64
  ```
71
65
 
72
66
  Fastify first tries to match a content-type parser with a `string` value before
73
- trying to find a matching `RegExp`. If you provide overlapping content types,
74
- Fastify tries to find a matching content type by starting with the last one
75
- passed and ending with the first one. So if you want to specify a general
76
- content type more precisely, first specify the general content type and then the
77
- more specific one, like in the example below.
67
+ trying to find a matching `RegExp`. For overlapping content types, it starts
68
+ with the last one configured and ends with the first (last in, first out).
69
+ To specify a general content type more precisely, first specify the general
70
+ type, then the specific one, as shown below.
78
71
 
79
72
  ```js
80
73
  // Here only the second content type parser is called because its value also matches the first one
@@ -88,10 +81,9 @@ fastify.addContentTypeParser('application/vnd.custom+xml', (request, body, done)
88
81
  ```
89
82
 
90
83
  ### Using addContentTypeParser with fastify.register
91
- When using `addContentTypeParser` in combination with `fastify.register`,
92
- `await` should not be used when registering routes. Using `await` causes
93
- the route registration to be asynchronous and can lead to routes being registered
94
- before the addContentTypeParser has been set.
84
+ When using `addContentTypeParser` with `fastify.register`, avoid `await`
85
+ when registering routes. Using `await` makes route registration asynchronous,
86
+ potentially registering routes before `addContentTypeParser` is set.
95
87
 
96
88
  #### Correct Usage
97
89
  ```js
@@ -109,14 +101,13 @@ fastify.register((fastify, opts) => {
109
101
  });
110
102
  ```
111
103
 
112
- Besides the `addContentTypeParser` API there are further APIs that can be used.
113
- These are `hasContentTypeParser`, `removeContentTypeParser` and
114
- `removeAllContentTypeParsers`.
104
+ In addition to `addContentTypeParser`, the `hasContentTypeParser`,
105
+ `removeContentTypeParser`, and `removeAllContentTypeParsers` APIs are available.
115
106
 
116
107
  #### hasContentTypeParser
117
108
 
118
- You can use the `hasContentTypeParser` API to find if a specific content type
119
- parser already exists.
109
+ Use the `hasContentTypeParser` API to check if a specific content type parser
110
+ exists.
120
111
 
121
112
  ```js
122
113
  if (!fastify.hasContentTypeParser('application/jsoff')){
@@ -130,8 +121,8 @@ if (!fastify.hasContentTypeParser('application/jsoff')){
130
121
 
131
122
  #### removeContentTypeParser
132
123
 
133
- With `removeContentTypeParser` a single or an array of content types can be
134
- removed. The method supports `string` and `RegExp` content types.
124
+ `removeContentTypeParser` can remove a single content type or an array of
125
+ content types, supporting both `string` and `RegExp`.
135
126
 
136
127
  ```js
137
128
  fastify.addContentTypeParser('text/xml', function (request, payload, done) {
@@ -145,16 +136,11 @@ fastify.removeContentTypeParser(['application/json', 'text/plain'])
145
136
  ```
146
137
 
147
138
  #### removeAllContentTypeParsers
148
-
149
- In the example from just above, it is noticeable that we need to specify each
150
- content type that we want to remove. To solve this problem Fastify provides the
151
- `removeAllContentTypeParsers` API. This can be used to remove all currently
152
- existing content type parsers. In the example below we achieve the same as in
153
- the example above except that we do not need to specify each content type to
154
- delete. Just like `removeContentTypeParser`, this API supports encapsulation.
155
- The API is especially useful if you want to register a [catch-all content type
156
- parser](#catch-all) that should be executed for every content type and the
157
- built-in parsers should be ignored as well.
139
+ The `removeAllContentTypeParsers` API removes all existing content type parsers
140
+ eliminating the need to specify each one individually. This API supports
141
+ encapsulation and is useful for registering a
142
+ [catch-all content type parser](#catch-all) that should be executed for every
143
+ content type, ignoring built-in parsers.
158
144
 
159
145
  ```js
160
146
  fastify.removeAllContentTypeParsers()
@@ -166,18 +152,16 @@ fastify.addContentTypeParser('text/xml', function (request, payload, done) {
166
152
  })
167
153
  ```
168
154
 
169
- **Notice**: The old syntaxes `function(req, done)` and `async function(req)` for
170
- the parser are still supported but they are deprecated.
155
+ > 🛈 Note: `function(req, done)` and `async function(req)` are
156
+ > still supported but deprecated.
171
157
 
172
158
  #### Body Parser
173
- You can parse the body of a request in two ways. The first one is shown above:
174
- you add a custom content type parser and handle the request stream. In the
175
- second one, you should pass a `parseAs` option to the `addContentTypeParser`
176
- API, where you declare how you want to get the body. It could be of type
177
- `'string'` or `'buffer'`. If you use the `parseAs` option, Fastify will
178
- internally handle the stream and perform some checks, such as the [maximum
179
- size](./Server.md#factory-body-limit) of the body and the content length. If the
180
- limit is exceeded the custom parser will not be invoked.
159
+ The request body can be parsed in two ways. First, add a custom content type
160
+ parser and handle the request stream. Or second, use the `parseAs` option in the
161
+ `addContentTypeParser` API, specifying `'string'` or `'buffer'`. Fastify will
162
+ handle the stream, check the [maximum size](./Server.md#factory-body-limit) of
163
+ the body, and the content length. If the limit is exceeded, the custom parser
164
+ will not be invoked.
181
165
  ```js
182
166
  fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
183
167
  try {
@@ -195,15 +179,14 @@ See
195
179
  for an example.
196
180
 
197
181
  ##### Custom Parser Options
198
- + `parseAs` (string): Either `'string'` or `'buffer'` to designate how the
199
- incoming data should be collected. Default: `'buffer'`.
182
+ + `parseAs` (string): `'string'` or `'buffer'` to designate how the incoming
183
+ data should be collected. Default: `'buffer'`.
200
184
  + `bodyLimit` (number): The maximum payload size, in bytes, that the custom
201
185
  parser will accept. Defaults to the global body limit passed to the [`Fastify
202
186
  factory function`](./Server.md#bodylimit).
203
187
 
204
188
  #### Catch-All
205
- There are some cases where you need to catch all requests regardless of their
206
- content type. With Fastify, you can just use the `'*'` content type.
189
+ To catch all requests regardless of content type, use the `'*'` content type:
207
190
  ```js
208
191
  fastify.addContentTypeParser('*', function (request, payload, done) {
209
192
  let data = ''
@@ -213,12 +196,10 @@ fastify.addContentTypeParser('*', function (request, payload, done) {
213
196
  })
214
197
  })
215
198
  ```
199
+ All requests without a corresponding content type parser will be handled by
200
+ this function.
216
201
 
217
- Using this, all requests that do not have a corresponding content type parser
218
- will be handled by the specified function.
219
-
220
- This is also useful for piping the request stream. You can define a content
221
- parser like:
202
+ This is also useful for piping the request stream. Define a content parser like:
222
203
 
223
204
  ```js
224
205
  fastify.addContentTypeParser('*', function (request, payload, done) {
@@ -226,7 +207,7 @@ fastify.addContentTypeParser('*', function (request, payload, done) {
226
207
  })
227
208
  ```
228
209
 
229
- and then access the core HTTP request directly for piping it where you want:
210
+ And then access the core HTTP request directly for piping:
230
211
 
231
212
  ```js
232
213
  app.post('/hello', (request, reply) => {
@@ -254,12 +235,11 @@ fastify.route({
254
235
  })
255
236
  ```
256
237
 
257
- For piping file uploads you may want to check out [this
258
- plugin](https://github.com/fastify/fastify-multipart).
238
+ For piping file uploads, check out
239
+ [`@fastify/multipart`](https://github.com/fastify/fastify-multipart).
259
240
 
260
- If you want the content type parser to be executed on all content types and not
261
- only on those that don't have a specific one, you should call the
262
- `removeAllContentTypeParsers` method first.
241
+ To execute the content type parser on all content types, call
242
+ `removeAllContentTypeParsers` first.
263
243
 
264
244
  ```js
265
245
  // Without this call, the request body with the content type application/json would be processed by the built-in JSON parser