fastify 5.3.1 → 5.3.3

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 (50) hide show
  1. package/.vscode/settings.json +15 -15
  2. package/docs/Guides/Benchmarking.md +1 -1
  3. package/docs/Guides/Ecosystem.md +7 -2
  4. package/docs/Guides/Serverless.md +28 -69
  5. package/docs/Reference/Errors.md +0 -2
  6. package/docs/Reference/Server.md +17 -1
  7. package/eslint.config.js +17 -9
  8. package/fastify.js +7 -3
  9. package/lib/decorate.js +2 -2
  10. package/lib/errors.js +0 -8
  11. package/lib/logger-factory.js +1 -1
  12. package/lib/logger-pino.js +2 -2
  13. package/lib/reply.js +2 -2
  14. package/lib/request.js +1 -1
  15. package/lib/server.js +30 -51
  16. package/lib/validation.js +1 -1
  17. package/package.json +4 -4
  18. package/test/close-pipelining.test.js +5 -4
  19. package/test/decorator.test.js +422 -341
  20. package/test/helper.js +107 -69
  21. package/test/hooks.on-listen.test.js +255 -239
  22. package/test/hooks.on-ready.test.js +110 -92
  23. package/test/inject.test.js +114 -97
  24. package/test/input-validation.js +63 -53
  25. package/test/internals/errors.test.js +1 -11
  26. package/test/internals/hooks.test.js +17 -0
  27. package/test/issue-4959.test.js +2 -2
  28. package/test/logger/response.test.js +19 -20
  29. package/test/options.error-handler.test.js +1 -1
  30. package/test/options.test.js +1 -1
  31. package/test/output-validation.test.js +49 -70
  32. package/test/patch.error-handler.test.js +1 -1
  33. package/test/patch.test.js +1 -1
  34. package/test/plugin.1.test.js +71 -60
  35. package/test/promises.test.js +36 -30
  36. package/test/put.error-handler.test.js +1 -1
  37. package/test/put.test.js +1 -1
  38. package/test/reply-error.test.js +169 -148
  39. package/test/reply-trailers.test.js +119 -108
  40. package/test/schema-feature.test.js +309 -238
  41. package/test/schema-validation.test.js +74 -16
  42. package/test/stream.1.test.js +30 -27
  43. package/test/stream.2.test.js +20 -10
  44. package/test/stream.3.test.js +37 -31
  45. package/test/types/errors.test-d.ts +0 -1
  46. package/test/types/plugin.test-d.ts +1 -1
  47. package/test/types/register.test-d.ts +1 -1
  48. package/test/use-semicolon-delimiter.test.js +1 -1
  49. package/types/errors.d.ts +0 -1
  50. package/test/http2/missing-http2-module.test.js +0 -17
@@ -4,19 +4,19 @@
4
4
  "tab.activeBackground": "#0d0d0d",
5
5
  "tab.activeBorder": "#ffff00"
6
6
  },
7
- "activityBar.background": "#FBE7B2",
8
- "activityBar.foreground": "#52358C",
9
- "activityBar.inactiveForeground": "#616161",
10
- "activityBar.activeBorder": "#04184d",
11
- "activityBar.activeBackground": "#C3B48B",
12
- "activityBar.border": "#C3B48B",
13
- "titleBar.activeBackground": "#D2BE88",
14
- "titleBar.activeForeground": "#52358C",
15
- "titleBar.inactiveBackground": "#bdb59c",
16
- "titleBar.inactiveForeground": "#616161",
17
- "titleBar.border": "#C3B48B",
18
- "statusBar.background": "#E9DBB7",
19
- "statusBar.foreground": "#52358C",
20
- "statusBar.border": "#C3B48B"
7
+ "activityBar.background": "#7AC6C8",
8
+ "activityBar.foreground": "#0B2A34",
9
+ "activityBar.inactiveForeground": "#1e2021",
10
+ "activityBar.activeBorder": "#853937",
11
+ "activityBar.activeBackground": "#3F7F81",
12
+ "activityBar.border": "#3F7F81",
13
+ "titleBar.activeBackground": "#549B9D",
14
+ "titleBar.activeForeground": "#0B2A34",
15
+ "titleBar.inactiveBackground": "#727f7f",
16
+ "titleBar.inactiveForeground": "#1e2021",
17
+ "titleBar.border": "#3F7F81",
18
+ "statusBar.background": "#71ACAD",
19
+ "statusBar.foreground": "#0B2A34",
20
+ "statusBar.border": "#3F7F81"
21
21
  }
22
- }
22
+ }
@@ -12,7 +12,7 @@ The modules we will use:
12
12
  tool written in node.
13
13
  - [Branch-comparer](https://github.com/StarpTech/branch-comparer): Checkout
14
14
  multiple git branches, execute scripts, and log the results.
15
- - [Concurrently](https://github.com/kimmobrunfeldt/concurrently): Run commands
15
+ - [Concurrently](https://github.com/open-cli-tools/concurrently): Run commands
16
16
  concurrently.
17
17
  - [Npx](https://github.com/npm/npx): NPM package runner used to run scripts
18
18
  against different Node.js Versions and execute local binaries. Shipped with
@@ -40,8 +40,6 @@ section.
40
40
  plugin for adding
41
41
  [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) protection to
42
42
  Fastify.
43
- - [`@fastify/diagnostics-channel`](https://github.com/fastify/fastify-diagnostics-channel)
44
- Plugin to deal with `diagnostics_channel` on Fastify.
45
43
  - [`@fastify/elasticsearch`](https://github.com/fastify/fastify-elasticsearch)
46
44
  Plugin to share the same ES client.
47
45
  - [`@fastify/env`](https://github.com/fastify/fastify-env) Load and check
@@ -200,6 +198,9 @@ section.
200
198
  to go!
201
199
  A plugin to implement [Lyra](https://github.com/nearform/lyra) search engine
202
200
  on Fastify
201
+ - [`@inaiat/fastify-papr`](https://github.com/inaiat/fastify-papr)
202
+ A plugin to integrate [Papr](https://github.com/plexinc/papr),
203
+ the MongoDB ORM for TypeScript & MongoDB, with Fastify.
203
204
  - [`@jerome1337/fastify-enforce-routes-pattern`](https://github.com/Jerome1337/fastify-enforce-routes-pattern)
204
205
  A Fastify plugin that enforces naming pattern for routes path.
205
206
  - [`@joggr/fastify-prisma`](https://github.com/joggrdocs/fastify-prisma)
@@ -737,9 +738,13 @@ middlewares into Fastify plugins
737
738
  generator by directory structure.
738
739
  - [`fastify-flux`](https://github.com/Jnig/fastify-flux) Tool for building
739
740
  Fastify APIs using decorators and convert Typescript interface to JSON Schema.
741
+ - [`jeasx`](https://www.jeasx.dev)
742
+ A flexible server-rendering framework built on Fastify
743
+ that leverages asynchronous JSX to simplify web development.
740
744
  - [`simple-tjscli`](https://github.com/imjuni/simple-tjscli) CLI tool to
741
745
  generate JSON Schema from TypeScript interfaces.
742
746
  - [`vite-plugin-fastify`](https://github.com/Vanilla-IceCream/vite-plugin-fastify)
743
747
  Fastify plugin for Vite with Hot-module Replacement.
744
748
  - [`vite-plugin-fastify-routes`](https://github.com/Vanilla-IceCream/vite-plugin-fastify-routes)
745
749
  File-based routing for Fastify applications using Vite.
750
+
@@ -1,20 +1,20 @@
1
1
  <h1 align="center">Serverless</h1>
2
2
 
3
3
  Run serverless applications and REST APIs using your existing Fastify
4
- application. By default, Fastify will not work on your serverless platform of
5
- choice, you will need to make some small changes to fix this. This document
6
- contains a small guide for the most popular serverless providers and how to use
4
+ application. You may need to make code changes to work on your
5
+ serverless platform of choice. This document contains a small guide
6
+ for the most popular serverless providers and how to use
7
7
  Fastify with them.
8
8
 
9
9
  #### Should you use Fastify in a serverless platform?
10
10
 
11
- That is up to you! Keep in mind that functions as a service should always use
11
+ That is up to you! Keep in mind, functions as a service should always use
12
12
  small and focused functions, but you can also run an entire web application with
13
13
  them. It is important to remember that the bigger the application the slower the
14
14
  initial boot will be. The best way to run Fastify applications in serverless
15
- environments is to use platforms like Google Cloud Run, AWS Fargate, and Azure
16
- Container Instances, where the server can handle multiple requests at the same
17
- time and make full use of Fastify's features.
15
+ environments is to use platforms like Google Cloud Run, AWS Fargate, Azure
16
+ Container Instances, and Vercel where the server can handle multiple requests
17
+ at the same time and make full use of Fastify's features.
18
18
 
19
19
  One of the best features of using Fastify in serverless applications is the ease
20
20
  of development. In your local environment, you will always run the Fastify
@@ -136,7 +136,6 @@ of serverless applications to the cloud.
136
136
 
137
137
  [Genezio has a dedicated guide for deploying a Fastify application.](https://genezio.com/docs/frameworks/fastify/)
138
138
 
139
-
140
139
  ## Google Cloud Functions
141
140
 
142
141
  ### Creation of Fastify instance
@@ -238,14 +237,13 @@ npx @google-cloud/functions-framework --target=fastifyFunction
238
237
  Or add this command to your `package.json` scripts:
239
238
  ```json
240
239
  "scripts": {
241
- ...
242
- "dev": "npx @google-cloud/functions-framework --target=fastifyFunction"
243
- ...
240
+ ...
241
+ "dev": "npx @google-cloud/functions-framework --target=fastifyFunction"
242
+ ...
244
243
  }
245
244
  ```
246
245
  and run it with `npm run dev`.
247
246
 
248
-
249
247
  ### Deploy
250
248
  ```bash
251
249
  gcloud functions deploy fastifyFunction \
@@ -326,7 +324,7 @@ async function registerRoutes (fastify) {
326
324
  })
327
325
 
328
326
  // define your endpoints here...
329
- fastify.post("/some-route-here", async (request, reply) => {}
327
+ fastify.post("/some-route-here", async (request, reply) => {})
330
328
 
331
329
  fastify.get('/', async (request, reply) => {
332
330
  reply.send({message: 'Hello World!'})
@@ -377,7 +375,6 @@ firebase functions:log
377
375
  - [Fastify on Firebase Functions](https://github.com/lirantal/lemon-squeezy-firebase-webhook-fastify/blob/main/package.json)
378
376
  - [An article about HTTP webhooks on Firebase Functions and Fastify: A Practical Case Study with Lemon Squeezy](https://lirantal.com/blog/http-webhooks-firebase-functions-fastify-practical-case-study-lemon-squeezy)
379
377
 
380
-
381
378
  ## Google Cloud Run
382
379
 
383
380
  Unlike AWS Lambda or Google Cloud Functions, Google Cloud Run is a serverless
@@ -463,7 +460,7 @@ CMD [ "npm", "start" ]
463
460
  To keep build artifacts out of your container (which keeps it small and improves
464
461
  build times) add a `.dockerignore` file like the one below:
465
462
 
466
- ```.dockerignore
463
+ ```dockerignore
467
464
  Dockerfile
468
465
  README.md
469
466
  node_modules
@@ -490,12 +487,11 @@ gcloud beta run deploy --image gcr.io/PROJECT-ID/APP-NAME --platform managed
490
487
 
491
488
  Your app will be accessible from the URL GCP provides.
492
489
 
493
-
494
490
  ## netlify-lambda
495
491
 
496
492
  First, please perform all preparation steps related to **AWS Lambda**.
497
493
 
498
- Create a folder called `functions`, then create `server.js` (and your endpoint
494
+ Create a folder called `functions`, then create `server.js` (and your endpoint
499
495
  path will be `server.js`) inside the `functions` folder.
500
496
 
501
497
  ### functions/server.js
@@ -564,9 +560,9 @@ Add this command to your `package.json` *scripts*
564
560
 
565
561
  ```json
566
562
  "scripts": {
567
- ...
568
- "build:functions": "netlify-lambda build functions --config ./webpack.config.netlify.js"
569
- ...
563
+ ...
564
+ "build:functions": "netlify-lambda build functions --config ./webpack.config.netlify.js"
565
+ ...
570
566
  }
571
567
  ```
572
568
 
@@ -574,54 +570,17 @@ Then it should work fine.
574
570
 
575
571
  ## Vercel
576
572
 
577
- [Vercel](https://vercel.com) provides zero-configuration deployment for Node.js
578
- applications. To use it now, it is as simple as configuring your `vercel.json`
579
- file like the following:
580
-
581
- ```json
582
- {
583
- "rewrites": [
584
- {
585
- "source": "/(.*)",
586
- "destination": "/api/serverless.js"
587
- }
588
- ]
589
- }
590
- ```
591
-
592
- Then, write `api/serverless.js` like so:
593
-
594
- ```js
595
- "use strict";
596
-
597
- // Read the .env file.
598
- import * as dotenv from "dotenv";
599
- dotenv.config();
573
+ [Vercel](https://vercel.com) fully supports deploying Fastify applications.
574
+ Additionally, with Vercel's
575
+ [Fluid compute](https://vercel.com/docs/functions/fluid-compute), you can combine
576
+ server-like concurrency with the autoscaling properties of traditional
577
+ serverless functions.
600
578
 
601
- // Require the framework
602
- import Fastify from "fastify";
579
+ Get started with the
580
+ [Fastify Node.js template on Vercel](
581
+ https://vercel.com/templates/other/fastify-serverless-function).
603
582
 
604
- // Instantiate Fastify with some config
605
- const app = Fastify({
606
- logger: true,
607
- });
608
-
609
- // Register your application as a normal plugin.
610
- app.register(import("../src/app.js"));
611
-
612
- export default async (req, res) => {
613
- await app.ready();
614
- app.server.emit('request', req, res);
615
- }
616
- ```
617
-
618
- In `src/app.js` define the plugin.
619
- ```js
620
- async function routes (fastify, options) {
621
- fastify.get('/', async (request, reply) => {
622
- return { hello: 'world' }
623
- })
624
- }
625
-
626
- export default routes;
627
- ```
583
+ [Fluid compute](https://vercel.com/docs/functions/fluid-compute) currently
584
+ requires an explicit opt-in. Learn more about enabling Fluid compute
585
+ [here](
586
+ https://vercel.com/docs/functions/fluid-compute#how-to-enable-fluid-compute).
@@ -69,7 +69,6 @@
69
69
  - [FST_ERR_SCH_VALIDATION_BUILD](#fst_err_sch_validation_build)
70
70
  - [FST_ERR_SCH_SERIALIZATION_BUILD](#fst_err_sch_serialization_build)
71
71
  - [FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX](#fst_err_sch_response_schema_not_nested_2xx)
72
- - [FST_ERR_HTTP2_INVALID_VERSION](#fst_err_http2_invalid_version)
73
72
  - [FST_ERR_INIT_OPTS_INVALID](#fst_err_init_opts_invalid)
74
73
  - [FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE](#fst_err_force_close_connections_idle_not_available)
75
74
  - [FST_ERR_DUPLICATED_ROUTE](#fst_err_duplicated_route)
@@ -340,7 +339,6 @@ Below is a table with all the error codes used by Fastify.
340
339
  | <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) |
341
340
  | <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) |
342
341
  | <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) |
343
- | <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) |
344
342
  | <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) |
345
343
  | <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) |
346
344
  | <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) |
@@ -1529,7 +1529,7 @@ plugins.
1529
1529
  > 🛈 Note:
1530
1530
  > Some config properties from the request object will be
1531
1531
  > undefined inside the custom not found handler. E.g.:
1532
- > `request.routerPath`, `routerMethod` and `context.config`.
1532
+ > `request.routeOptions.url`, `routeOptions.method` and `routeOptions.config`.
1533
1533
  > This method design goal is to allow calling the common not found route.
1534
1534
  > To return a per-route customized 404 response, you can do it in
1535
1535
  > the response itself.
@@ -1574,6 +1574,22 @@ if (statusCode >= 500) {
1574
1574
  log.error(error)
1575
1575
  }
1576
1576
  ```
1577
+
1578
+ > ⚠ Warning:
1579
+ > Avoid calling setErrorHandler multiple times in the same scope.
1580
+ > Only the last handler will take effect, and previous ones will be silently overridden.
1581
+ >
1582
+ > Incorrect usage:
1583
+ > ```js
1584
+ > app.setErrorHandler(function freeSomeResources () {
1585
+ > // Never executed, memory leaks
1586
+ > })
1587
+ >
1588
+ > app.setErrorHandler(function anotherErrorHandler () {
1589
+ > // Overrides the previous handler
1590
+ > })
1591
+ > ```
1592
+
1577
1593
  #### setChildLoggerFactory
1578
1594
  <a id="set-child-logger-factory"></a>
1579
1595
 
package/eslint.config.js CHANGED
@@ -1,11 +1,19 @@
1
1
  'use strict'
2
+ const neostandard = require('neostandard')
2
3
 
3
- module.exports = require('neostandard')({
4
- ignores: [
5
- 'lib/configValidator.js',
6
- 'lib/error-serializer.js',
7
- 'test/same-shape.test.js',
8
- 'test/types/import.js'
9
- ],
10
- ts: true
11
- })
4
+ module.exports = [
5
+ ...neostandard({
6
+ ignores: [
7
+ 'lib/configValidator.js',
8
+ 'lib/error-serializer.js',
9
+ 'test/same-shape.test.js',
10
+ 'test/types/import.js'
11
+ ],
12
+ ts: true
13
+ }),
14
+ {
15
+ rules: {
16
+ 'comma-dangle': ['error', 'never']
17
+ }
18
+ }
19
+ ]
package/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '5.3.1'
3
+ const VERSION = '5.3.2'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('node:http')
@@ -681,8 +681,12 @@ function fastify (options) {
681
681
  this[kHooks].add(name, fn)
682
682
  } else {
683
683
  this.after((err, done) => {
684
- _addHook.call(this, name, fn)
685
- done(err)
684
+ try {
685
+ _addHook.call(this, name, fn)
686
+ done(err)
687
+ } catch (err) {
688
+ done(err)
689
+ }
686
690
  })
687
691
  }
688
692
  return this
package/lib/decorate.js CHANGED
@@ -4,7 +4,7 @@ const {
4
4
  kReply,
5
5
  kRequest,
6
6
  kState,
7
- kHasBeenDecorated,
7
+ kHasBeenDecorated
8
8
  } = require('./symbols.js')
9
9
 
10
10
  const {
@@ -13,7 +13,7 @@ const {
13
13
  FST_ERR_DEC_AFTER_START,
14
14
  FST_ERR_DEC_REFERENCE_TYPE,
15
15
  FST_ERR_DEC_DEPENDENCY_INVALID_TYPE,
16
- FST_ERR_DEC_UNDECLARED,
16
+ FST_ERR_DEC_UNDECLARED
17
17
  } = require('./errors')
18
18
 
19
19
  function decorate (instance, name, fn, dependencies) {
package/lib/errors.js CHANGED
@@ -328,14 +328,6 @@ const codes = {
328
328
  'response schemas should be nested under a valid status code, e.g { 2xx: { type: "object" } }'
329
329
  ),
330
330
 
331
- /**
332
- * http2
333
- */
334
- FST_ERR_HTTP2_INVALID_VERSION: createError(
335
- 'FST_ERR_HTTP2_INVALID_VERSION',
336
- 'HTTP2 is available only from node >= 8.8.1'
337
- ),
338
-
339
331
  /**
340
332
  * initialConfig
341
333
  */
@@ -132,5 +132,5 @@ module.exports = {
132
132
  defaultChildLoggerFactory,
133
133
  createLogger,
134
134
  validateLogger,
135
- now,
135
+ now
136
136
  }
@@ -9,7 +9,7 @@
9
9
  const pino = require('pino')
10
10
  const { serializersSym } = pino.symbols
11
11
  const {
12
- FST_ERR_LOG_INVALID_DESTINATION,
12
+ FST_ERR_LOG_INVALID_DESTINATION
13
13
  } = require('./errors')
14
14
 
15
15
  function createPinoLogger (opts) {
@@ -64,5 +64,5 @@ const serializers = {
64
64
 
65
65
  module.exports = {
66
66
  serializers,
67
- createPinoLogger,
67
+ createPinoLogger
68
68
  }
package/lib/reply.js CHANGED
@@ -22,7 +22,7 @@ const {
22
22
  kReplyCacheSerializeFns,
23
23
  kSchemaController,
24
24
  kOptions,
25
- kRouteContext,
25
+ kRouteContext
26
26
  } = require('./symbols.js')
27
27
  const {
28
28
  onSendHookRunner,
@@ -53,7 +53,7 @@ const {
53
53
  FST_ERR_BAD_TRAILER_VALUE,
54
54
  FST_ERR_MISSING_SERIALIZATION_FN,
55
55
  FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN,
56
- FST_ERR_DEC_UNDECLARED,
56
+ FST_ERR_DEC_UNDECLARED
57
57
  } = require('./errors')
58
58
  const decorators = require('./decorate')
59
59
 
package/lib/request.js CHANGED
@@ -11,7 +11,7 @@ const {
11
11
  kOptions,
12
12
  kRequestCacheValidateFns,
13
13
  kRouteContext,
14
- kRequestOriginalUrl,
14
+ kRequestOriginalUrl
15
15
  } = require('./symbols')
16
16
  const { FST_ERR_REQ_INVALID_VALIDATION_INVOCATION, FST_ERR_DEC_UNDECLARED } = require('./errors')
17
17
  const decorators = require('./decorate')
package/lib/server.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const http = require('node:http')
4
4
  const https = require('node:https')
5
+ const http2 = require('node:http2')
5
6
  const dns = require('node:dns')
6
7
  const os = require('node:os')
7
8
 
@@ -9,7 +10,6 @@ const { kState, kOptions, kServerBindings } = require('./symbols')
9
10
  const { FSTWRN003 } = require('./warnings')
10
11
  const { onListenHookRunner } = require('./hooks')
11
12
  const {
12
- FST_ERR_HTTP2_INVALID_VERSION,
13
13
  FST_ERR_REOPENED_CLOSE_SERVER,
14
14
  FST_ERR_REOPENED_SERVER,
15
15
  FST_ERR_LISTEN_OPTIONS_INVALID
@@ -98,7 +98,6 @@ function createServer (options, httpHandler) {
98
98
 
99
99
  if (cb === undefined) {
100
100
  const listening = listenPromise.call(this, server, listenOptions)
101
- /* istanbul ignore else */
102
101
  return listening.then(address => {
103
102
  return new Promise((resolve, reject) => {
104
103
  if (host === 'localhost') {
@@ -192,7 +191,6 @@ function multipleBindings (mainServer, httpHandler, serverOpts, listenOptions, o
192
191
  // to the secondary servers. It is valid only when the user is
193
192
  // listening on localhost
194
193
  const originUnref = mainServer.unref
195
- /* c8 ignore next 4 */
196
194
  mainServer.unref = function () {
197
195
  originUnref.call(mainServer)
198
196
  mainServer.emit('unref')
@@ -218,7 +216,8 @@ function listenCallback (server, listenOptions) {
218
216
 
219
217
  if (this[kState].listening && this[kState].closing) {
220
218
  return listenOptions.cb(new FST_ERR_REOPENED_CLOSE_SERVER(), null)
221
- } else if (this[kState].listening) {
219
+ }
220
+ if (this[kState].listening) {
222
221
  return listenOptions.cb(new FST_ERR_REOPENED_SERVER(), null)
223
222
  }
224
223
 
@@ -234,7 +233,8 @@ function listenCallback (server, listenOptions) {
234
233
  function listenPromise (server, listenOptions) {
235
234
  if (this[kState].listening && this[kState].closing) {
236
235
  return Promise.reject(new FST_ERR_REOPENED_CLOSE_SERVER())
237
- } else if (this[kState].listening) {
236
+ }
237
+ if (this[kState].listening) {
238
238
  return Promise.reject(new FST_ERR_REOPENED_SERVER())
239
239
  }
240
240
 
@@ -272,41 +272,38 @@ function listenPromise (server, listenOptions) {
272
272
  }
273
273
 
274
274
  function getServerInstance (options, httpHandler) {
275
- let server = null
276
- // node@20 do not accepts options as boolean
277
- // we need to provide proper https option
278
- const httpsOptions = options.https === true ? {} : options.https
279
275
  if (options.serverFactory) {
280
- server = options.serverFactory(httpHandler, options)
281
- } else if (options.http2) {
282
- if (typeof httpsOptions === 'object') {
283
- server = http2().createSecureServer(httpsOptions, httpHandler)
284
- } else {
285
- server = http2().createServer(httpHandler)
286
- }
287
- server.on('session', sessionTimeout(options.http2SessionTimeout))
288
- } else {
289
- // this is http1
290
- if (httpsOptions) {
291
- server = https.createServer(httpsOptions, httpHandler)
292
- } else {
293
- server = http.createServer(options.http, httpHandler)
294
- }
295
- server.keepAliveTimeout = options.keepAliveTimeout
296
- server.requestTimeout = options.requestTimeout
297
- // we treat zero as null
298
- // and null is the default setting from nodejs
299
- // so we do not pass the option to server
300
- if (options.maxRequestsPerSocket > 0) {
301
- server.maxRequestsPerSocket = options.maxRequestsPerSocket
302
- }
276
+ // User provided server instance
277
+ return options.serverFactory(httpHandler, options)
303
278
  }
304
279
 
305
- if (!options.serverFactory) {
280
+ // We have accepted true as a valid way to init https but node requires an options obj
281
+ const httpsOptions = options.https === true ? {} : options.https
282
+
283
+ if (options.http2) {
284
+ const server = typeof httpsOptions === 'object' ? http2.createSecureServer(httpsOptions, httpHandler) : http2.createServer(options.http, httpHandler)
285
+ server.on('session', (session) => session.setTimeout(options.http2SessionTimeout, function closeSession () {
286
+ this.close()
287
+ }))
288
+
306
289
  server.setTimeout(options.connectionTimeout)
290
+
291
+ return server
307
292
  }
293
+
294
+ // HTTP1 server instance
295
+ const server = httpsOptions ? https.createServer(httpsOptions, httpHandler) : http.createServer(options.http, httpHandler)
296
+ server.keepAliveTimeout = options.keepAliveTimeout
297
+ server.requestTimeout = options.requestTimeout
298
+ server.setTimeout(options.connectionTimeout)
299
+ // We treat zero as null(node default) so we do not pass zero to the server instance
300
+ if (options.maxRequestsPerSocket > 0) {
301
+ server.maxRequestsPerSocket = options.maxRequestsPerSocket
302
+ }
303
+
308
304
  return server
309
305
  }
306
+
310
307
  /**
311
308
  * Inspects the provided `server.address` object and returns a
312
309
  * normalized list of IP address strings. Normalization in this
@@ -355,21 +352,3 @@ function logServerAddress (server, listenTextResolver) {
355
352
  }
356
353
  return addresses[0]
357
354
  }
358
-
359
- function http2 () {
360
- try {
361
- return require('node:http2')
362
- } catch (err) {
363
- throw new FST_ERR_HTTP2_INVALID_VERSION()
364
- }
365
- }
366
-
367
- function sessionTimeout (timeout) {
368
- return function (session) {
369
- session.setTimeout(timeout, close)
370
- }
371
- }
372
-
373
- function close () {
374
- this.close()
375
- }
package/lib/validation.js CHANGED
@@ -261,7 +261,7 @@ function wrapValidationError (result, dataVar, schemaErrorFormatter) {
261
261
  */
262
262
  function getEssenceMediaType (header) {
263
263
  if (!header) return ''
264
- return header.split(';', 1)[0].trim().toLowerCase()
264
+ return header.split(/[ ;]/, 1)[0].trim().toLowerCase()
265
265
  }
266
266
 
267
267
  module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "5.3.1",
3
+ "version": "5.3.3",
4
4
  "description": "Fast and low overhead web framework, for Node.js",
5
5
  "main": "fastify.js",
6
6
  "type": "commonjs",
@@ -172,14 +172,14 @@
172
172
  "ajv-i18n": "^4.2.0",
173
173
  "ajv-merge-patch": "^5.0.1",
174
174
  "autocannon": "^8.0.0",
175
- "borp": "^0.19.0",
175
+ "borp": "^0.20.0",
176
176
  "branch-comparer": "^1.1.0",
177
177
  "concurrently": "^9.1.2",
178
178
  "cross-env": "^7.0.3",
179
179
  "eslint": "^9.0.0",
180
180
  "fast-json-body": "^1.1.0",
181
181
  "fastify-plugin": "^5.0.0",
182
- "fluent-json-schema": "^5.0.0",
182
+ "fluent-json-schema": "^6.0.0",
183
183
  "h2url": "^0.2.0",
184
184
  "http-errors": "^2.0.0",
185
185
  "joi": "^17.12.3",
@@ -192,7 +192,7 @@
192
192
  "simple-get": "^4.0.1",
193
193
  "split2": "^4.2.0",
194
194
  "tap": "^21.0.0",
195
- "tsd": "^0.31.0",
195
+ "tsd": "^0.32.0",
196
196
  "typescript": "~5.8.2",
197
197
  "undici": "^6.13.0",
198
198
  "vary": "^1.1.2",
@@ -59,10 +59,11 @@ test('Should close the socket abruptly - pipelining - return503OnClosing: false'
59
59
  instance.request({ path: '/', method: 'GET' })
60
60
  ])
61
61
 
62
- t.assert.strictEqual(responses[0].status, 'fulfilled')
63
- t.assert.strictEqual(responses[1].status, 'fulfilled')
64
- t.assert.strictEqual(responses[2].status, 'rejected')
65
- t.assert.strictEqual(responses[3].status, 'rejected')
62
+ const fulfilled = responses.filter(r => r.status === 'fulfilled')
63
+ const rejected = responses.filter(r => r.status === 'rejected')
64
+
65
+ t.assert.strictEqual(fulfilled.length, 2)
66
+ t.assert.strictEqual(rejected.length, 2)
66
67
 
67
68
  await instance.close()
68
69
  })