fastify 4.28.0 → 4.29.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.
- package/SPONSORS.md +2 -0
- package/docs/Guides/Migration-Guide-V4.md +52 -0
- package/docs/Reference/Routes.md +2 -1
- package/docs/Reference/Server.md +2 -0
- package/docs/Reference/Validation-and-Serialization.md +22 -0
- package/docs/Reference/Warnings.md +2 -0
- package/fastify.js +2 -2
- package/lib/handleRequest.js +2 -1
- package/lib/reply.js +21 -25
- package/lib/route.js +2 -2
- package/lib/schemas.js +22 -5
- package/lib/server.js +20 -9
- package/lib/validation.js +23 -2
- package/lib/warnings.js +6 -0
- package/package.json +1 -1
- package/test/close.test.js +4 -1
- package/test/copy.test.js +12 -5
- package/test/internals/validation.test.js +34 -8
- package/test/json-shorthand.test.js +131 -0
- package/test/listen.1.test.js +36 -0
- package/test/listen.5.test.js +99 -0
- package/test/mkcol.test.js +7 -4
- package/test/move.test.js +9 -6
- package/test/route.8.test.js +27 -0
- package/test/schema-feature.test.js +21 -0
- package/test/schema-validation.test.js +136 -0
- package/test/stream-serializers.test.js +37 -0
- package/test/throw.test.js +2 -2
- package/test/types/hooks.test-d.ts +4 -2
- package/test/types/route.test-d.ts +23 -0
- package/test/types/schema.test-d.ts +19 -0
- package/test/web-api.test.js +75 -0
- package/types/hooks.d.ts +2 -0
- package/types/route.d.ts +2 -2
- package/.tap/processinfo/029eb7a1-1942-40bc-98e2-cef3b7a14b5e.json +0 -268
- package/.tap/processinfo/03c196c6-01c3-4268-a9b5-298dff18a873.json +0 -269
- package/.tap/processinfo/04bbabba-8611-4908-9092-dfa9fcc13327.json +0 -268
- package/.tap/processinfo/05d8a743-3edf-4e2d-ae5a-dc99d0855ba5.json +0 -272
- package/.tap/processinfo/07718963-36a8-4d87-82ad-366c877a5247.json +0 -268
- package/.tap/processinfo/08fe3bde-5814-4308-9158-cdf1e47391b7.json +0 -268
- package/.tap/processinfo/0a3e3fb0-eabf-4532-ae80-20434da22678.json +0 -268
- package/.tap/processinfo/0caf2a75-4b3a-46c4-9b41-c7e450e5e15f.json +0 -268
- package/.tap/processinfo/0cf35d52-e5b2-4884-bcf0-b0ab3017b689.json +0 -268
- package/.tap/processinfo/0e666134-5013-4ecd-9ee6-59b22716c39c.json +0 -268
- package/.tap/processinfo/1087b811-4ec4-4f91-92b4-a78a51a437de.json +0 -268
- package/.tap/processinfo/13709ed3-b68c-42cf-8472-b0c4b8a89d2b.json +0 -268
- package/.tap/processinfo/13ac2f18-d0e0-439f-bc86-2ff0119af857.json +0 -268
- package/.tap/processinfo/13e47e0e-f6e8-4381-8a42-923b661f4a4f.json +0 -268
- package/.tap/processinfo/143f7d43-b8e8-4666-b482-f28fb37160ee.json +0 -268
- package/.tap/processinfo/14f3801d-03ab-4db3-9df5-c5d47e0a8cf0.json +0 -270
- package/.tap/processinfo/15a07dad-4bcd-442c-95e0-30c31f2b9818.json +0 -273
- package/.tap/processinfo/191ad3ad-04d8-4fb9-b119-ad2811f9b925.json +0 -243
- package/.tap/processinfo/1b25d54b-62d3-44cd-b581-31e705522fae.json +0 -268
- package/.tap/processinfo/1b7cb260-f04b-4135-a4fe-093081c4706f.json +0 -268
- package/.tap/processinfo/1e395d63-4815-4c77-aa47-df3709cc0ef9.json +0 -268
- package/.tap/processinfo/1e7f6a54-3abf-4771-863a-585cba110aec.json +0 -268
- package/.tap/processinfo/21a15e1d-0b41-47d8-b03d-0ba130969034.json +0 -244
- package/.tap/processinfo/21e02016-9ecd-4983-8417-9c74d224644f.json +0 -269
- package/.tap/processinfo/2327d941-d0d5-4762-b386-02a9a27ad28e.json +0 -268
- package/.tap/processinfo/23d39204-eac9-4f57-8db4-ffa996227fbd.json +0 -268
- package/.tap/processinfo/2493875a-0ac6-4d53-993c-f44471fd0678.json +0 -268
- package/.tap/processinfo/2698669f-f1e7-4a12-a687-8d58177be2b0.json +0 -269
- package/.tap/processinfo/2862b053-0a3d-46d7-9381-ffcb06287609.json +0 -268
- package/.tap/processinfo/2ac1b8d6-ac92-40e2-a59a-7681069f487c.json +0 -268
- package/.tap/processinfo/2c75e5f7-c4ef-47e4-a1c4-105eef6c0fab.json +0 -242
- package/.tap/processinfo/2e2c45cd-718b-4e5a-bf88-f801630f2803.json +0 -268
- package/.tap/processinfo/2f9ca478-3e03-4cce-a0bc-fcdc86d7c316.json +0 -268
- package/.tap/processinfo/30e3117f-fb74-456f-8f02-527e9eb9fcc3.json +0 -268
- package/.tap/processinfo/332be679-63c7-4b49-8b87-ef55995ada2d.json +0 -268
- package/.tap/processinfo/37c36f95-07f9-4ef0-8ab4-9e107d51b605.json +0 -269
- package/.tap/processinfo/3874eae2-f3db-44ef-9a9f-c8169d4b2b76.json +0 -268
- package/.tap/processinfo/38a7c3da-a411-41d0-8993-9deefd23500d.json +0 -268
- package/.tap/processinfo/3a7b6dbd-e153-4ce5-b557-21fb82009983.json +0 -269
- package/.tap/processinfo/3c6731ec-936d-470f-b7b0-0c87b54be051.json +0 -268
- package/.tap/processinfo/3c850ea9-4ef0-4044-a3fd-fbadfa9d543e.json +0 -268
- package/.tap/processinfo/3e4e15e0-a325-46f0-be57-5fd374560b7a.json +0 -269
- package/.tap/processinfo/3ed868e0-887c-402a-9f22-b1fdb74b4da0.json +0 -268
- package/.tap/processinfo/405498d7-5854-4ce1-a7dc-06920932f26d.json +0 -268
- package/.tap/processinfo/40b7eb19-ae35-4490-8a11-eb91a573c590.json +0 -268
- package/.tap/processinfo/40bb1260-d856-4248-8939-a0a05e322041.json +0 -268
- package/.tap/processinfo/41252e0b-7f69-44cc-b356-dd94bcbfdb29.json +0 -268
- package/.tap/processinfo/418fa710-e2fd-4508-b533-c179958da464.json +0 -269
- package/.tap/processinfo/433ef009-63aa-48fe-8e5d-c725228fa2fc.json +0 -268
- package/.tap/processinfo/44bf577c-9c01-4197-bd29-2e1ae888c4d4.json +0 -268
- package/.tap/processinfo/458fb7f2-20b9-48a2-8853-403c9851f605.json +0 -268
- package/.tap/processinfo/46b9892b-bb23-4b86-b0fa-9297f08c611a.json +0 -268
- package/.tap/processinfo/46bd9aaf-6cf3-4bd5-b90d-e136a7299a8e.json +0 -268
- package/.tap/processinfo/4779aa5f-e57a-4fcc-87e2-7d0bd4fca27f.json +0 -268
- package/.tap/processinfo/47b73f4b-ab31-49e1-97fd-8436dbe4bdf3.json +0 -269
- package/.tap/processinfo/49dba52e-e0c9-445d-8e9d-6d9ebe3ce6c4.json +0 -268
- package/.tap/processinfo/4b1dbc61-4e65-4c56-9784-2036f369038a.json +0 -268
- package/.tap/processinfo/4b6f0b40-43ef-4668-83a0-e07e28509df5.json +0 -268
- package/.tap/processinfo/4c236f70-f532-460b-8f7a-dd973301d493.json +0 -268
- package/.tap/processinfo/4d92b707-a268-48b8-885b-004d3a288c41.json +0 -269
- package/.tap/processinfo/4ff10bae-7c97-4c0a-b712-6c0d2f8c0e8e.json +0 -270
- package/.tap/processinfo/50f95bd5-ae12-4d83-99f4-ae9b0690c6a8.json +0 -268
- package/.tap/processinfo/557e4a49-d99c-4a63-b2f2-f33d897ab874.json +0 -268
- package/.tap/processinfo/589fd21a-8319-4abf-8cf7-82cb4a463a4b.json +0 -269
- package/.tap/processinfo/5a872f3a-949f-40be-8004-d739d034255c.json +0 -272
- package/.tap/processinfo/5abc301a-23da-424d-891e-3afbaff9156c.json +0 -269
- package/.tap/processinfo/5c31614c-a766-4837-ab59-dd6977166f72.json +0 -253
- package/.tap/processinfo/5d1e90c8-d819-4901-b022-f9ea4cd81978.json +0 -268
- package/.tap/processinfo/5d283e67-f31d-4fa8-a559-a1d8e82ee046.json +0 -269
- package/.tap/processinfo/5df505bc-6a4b-4c41-822f-51e2d7111de8.json +0 -268
- package/.tap/processinfo/5eaf64a2-fbfd-40e7-b391-c30f744b2bf1.json +0 -269
- package/.tap/processinfo/5ef5ede0-6436-4938-8401-d32ad4bffd5d.json +0 -268
- package/.tap/processinfo/606f05c0-8293-41db-bc92-eea82123697f.json +0 -269
- package/.tap/processinfo/6446806d-6cab-4c1d-a9ed-6bccaf3c4ea9.json +0 -268
- package/.tap/processinfo/64da7e08-925d-444d-98de-6568c6115d8d.json +0 -269
- package/.tap/processinfo/6917da6d-d2dc-466a-a893-7fb7412dde96.json +0 -268
- package/.tap/processinfo/69bbeee0-c398-4ccf-98b3-fb625a63bab4.json +0 -268
- package/.tap/processinfo/6da6ea8f-3370-4703-b230-90159531f766.json +0 -268
- package/.tap/processinfo/6ecffe1f-3016-4c11-9294-b488baced99f.json +0 -268
- package/.tap/processinfo/6f23f41f-ccbd-48cb-9ab6-311db0cfb65c.json +0 -270
- package/.tap/processinfo/70168912-9bb2-4334-bb89-041f1764cddf.json +0 -268
- package/.tap/processinfo/713a674e-40e1-46b4-866e-949d57c1a9f9.json +0 -270
- package/.tap/processinfo/730254d4-eacb-4cdf-80f4-8da22341cde5.json +0 -268
- package/.tap/processinfo/7344e559-c546-416f-8f1b-0f9fe12c6f02.json +0 -268
- package/.tap/processinfo/7556217a-0155-448f-b4d4-bec1bb0f6040.json +0 -269
- package/.tap/processinfo/7572079c-166c-4c4c-85ff-89b9430b214f.json +0 -268
- package/.tap/processinfo/7808180f-1974-47cd-bba2-2d6b8b711d65.json +0 -273
- package/.tap/processinfo/796dde83-da66-4db2-8d27-d45a3627c9c7.json +0 -268
- package/.tap/processinfo/7979819f-3723-48be-9f55-be700e689441.json +0 -270
- package/.tap/processinfo/7a664d39-d7f5-42f9-89df-15563048fab6.json +0 -268
- package/.tap/processinfo/7b047b72-01d9-4217-857c-93341651b4b3.json +0 -269
- package/.tap/processinfo/7ce41af6-7961-45ae-8c6f-b6e1c5692a48.json +0 -268
- package/.tap/processinfo/7e1de1c6-127e-463d-9357-081ee33ef5ce.json +0 -269
- package/.tap/processinfo/81ac7a7f-b0c0-4ef6-82cb-c718ea84e152.json +0 -268
- package/.tap/processinfo/851a058f-a497-4b10-a0b7-c9182d9c4d5a.json +0 -268
- package/.tap/processinfo/86502974-c245-4194-ade4-d9c6fdbb757e.json +0 -268
- package/.tap/processinfo/86b9786f-4a98-43b8-882a-5f936b876f08.json +0 -241
- package/.tap/processinfo/8a3fe726-86ab-4300-8d73-7eacbbc02a05.json +0 -268
- package/.tap/processinfo/8adf928b-c963-4ba0-9c35-606fcbd8a2aa.json +0 -272
- package/.tap/processinfo/8b31a6d8-1a33-4a27-93ca-1c5b364be068.json +0 -240
- package/.tap/processinfo/8ec12773-6b18-49a2-8e52-874c797df965.json +0 -833
- package/.tap/processinfo/8edb9502-3420-42fb-a602-e5de93be2df1.json +0 -268
- package/.tap/processinfo/8fc572e6-9828-4f98-a49c-9e081b2193c4.json +0 -242
- package/.tap/processinfo/8fee2d30-c5dd-4fae-9cf2-2ef8dd0f90de.json +0 -834
- package/.tap/processinfo/92cc0496-5f26-4370-8212-18136b972f99.json +0 -268
- package/.tap/processinfo/93a3f064-3f6e-4f49-becb-f7925f2961a9.json +0 -268
- package/.tap/processinfo/967e3697-8310-4a19-8dd5-927ac8bd6c79.json +0 -269
- package/.tap/processinfo/97225e23-9d30-4287-b3f5-72bccebec50b.json +0 -268
- package/.tap/processinfo/9a363bc6-4e65-47e8-94ca-26a9db428fb4.json +0 -268
- package/.tap/processinfo/9d2fe462-57fa-43f1-b02c-d188f15de30b.json +0 -270
- package/.tap/processinfo/a00b6cda-feb7-4b8a-8179-4c43bc29d670.json +0 -269
- package/.tap/processinfo/a017cbd5-4ac7-49e1-8c77-1bf4f6e7f2a6.json +0 -271
- package/.tap/processinfo/a1277309-1984-48f8-b60b-f5e8639736be.json +0 -271
- package/.tap/processinfo/a16bf53e-4337-48ff-88fa-67f55738e0f5.json +0 -268
- package/.tap/processinfo/a3a9848f-440e-41bb-9b0b-568bcfee0ddc.json +0 -268
- package/.tap/processinfo/a468c11f-f2f1-4e92-9ba0-6d28b6569b72.json +0 -268
- package/.tap/processinfo/a5880465-68f1-46b3-84a5-0da389d0bc67.json +0 -268
- package/.tap/processinfo/a666f394-39b4-44ad-8e74-abebf74dde3b.json +0 -270
- package/.tap/processinfo/af09d8ca-7053-4410-b514-b22c47f5979f.json +0 -268
- package/.tap/processinfo/af203309-28aa-459d-a56e-d88833695521.json +0 -268
- package/.tap/processinfo/afa2f7b6-dcd2-4d90-bf3c-54ba8b6800eb.json +0 -268
- package/.tap/processinfo/b231291d-ef14-4ff0-85f9-38a73a5408f8.json +0 -268
- package/.tap/processinfo/b3d3f2a1-a9fc-4d88-b122-fae90248cd59.json +0 -268
- package/.tap/processinfo/b834bf83-26c4-403a-8e91-eb15fe4b0b5d.json +0 -268
- package/.tap/processinfo/b8786fd7-47df-4ac1-8d6f-2d4c7623c681.json +0 -268
- package/.tap/processinfo/b9758f53-7f5a-4b03-8684-8a42ad644e5a.json +0 -268
- package/.tap/processinfo/bd194ea2-a21a-4604-b225-ee48abf1e607.json +0 -242
- package/.tap/processinfo/bd7ced53-3872-43b7-ad73-3352e50b728b.json +0 -268
- package/.tap/processinfo/be50295b-7e50-46cd-8bf1-637bf222699c.json +0 -268
- package/.tap/processinfo/bec61dd9-aa52-4e6c-8e37-5c9c10e935fd.json +0 -268
- package/.tap/processinfo/c015adf9-1d60-447e-87b5-b2031fe55bba.json +0 -268
- package/.tap/processinfo/c0666afa-7f64-45bd-97fb-145df1380157.json +0 -268
- package/.tap/processinfo/c2c0c012-c1c0-4457-84d6-dadba8396c94.json +0 -268
- package/.tap/processinfo/c3dd3ecd-737b-47ce-a917-54341c7bbed3.json +0 -268
- package/.tap/processinfo/c41ac06d-64b8-4bb3-bf56-0551f5a48f4b.json +0 -268
- package/.tap/processinfo/c4235bfb-a2aa-4271-9c6b-3ceb370219b1.json +0 -268
- package/.tap/processinfo/c4e6f24f-288c-493c-b6f0-02924aeb6758.json +0 -270
- package/.tap/processinfo/c54227bb-4a7b-40bb-bfe6-b54fe55078f3.json +0 -268
- package/.tap/processinfo/c699de91-3b0b-4466-9418-6910a3eb640a.json +0 -269
- package/.tap/processinfo/c74e2f37-451a-4577-ac18-e597fbd9a1d4.json +0 -269
- package/.tap/processinfo/c90cccec-5b4b-445f-a935-ac22859675d0.json +0 -252
- package/.tap/processinfo/c9dd6c7d-0d16-45e5-87ae-117388bf2994.json +0 -268
- package/.tap/processinfo/ca2e48fb-58c5-47fc-ad2e-263838aea42c.json +0 -272
- package/.tap/processinfo/ca87351d-c710-45c1-838a-16bccac59874.json +0 -273
- package/.tap/processinfo/cdb4a671-5776-4944-91b9-c456c58841ef.json +0 -268
- package/.tap/processinfo/cf10fdc8-6a87-447a-9e12-45f447af61f3.json +0 -244
- package/.tap/processinfo/cf3f1f08-643e-4f24-82ca-40f7a349c3d1.json +0 -268
- package/.tap/processinfo/d091172a-06a5-469b-82a9-8fefe3dd99da.json +0 -240
- package/.tap/processinfo/d1675431-61d6-45f8-a010-6e654112a00a.json +0 -272
- package/.tap/processinfo/d2d54aa2-c221-4ad4-b6b7-0c58e3c3679c.json +0 -269
- package/.tap/processinfo/d4f3c95a-ddbe-419d-bce0-dd6acceee21f.json +0 -268
- package/.tap/processinfo/d54ed8f1-43c3-478a-90d3-2c8aced723f2.json +0 -269
- package/.tap/processinfo/d6e5a2a6-4647-4d98-916c-aec4ace54a65.json +0 -268
- package/.tap/processinfo/d7280c64-45e6-4b12-affc-3ac9a5d4014a.json +0 -268
- package/.tap/processinfo/d82c8367-d825-4405-88df-07298f6ef840.json +0 -269
- package/.tap/processinfo/d8f97e53-e921-4d33-9c8d-2f7e807a9425.json +0 -268
- package/.tap/processinfo/da546a73-9714-4f8c-bdbb-e42730edbcfa.json +0 -268
- package/.tap/processinfo/da7fb7fb-1da4-49f8-a3ee-d4ea623c01a5.json +0 -268
- package/.tap/processinfo/daa6a016-4f0c-4050-923c-2022e0bb21d8.json +0 -268
- package/.tap/processinfo/db9a251d-8540-4719-b464-e7d5febd97d1.json +0 -240
- package/.tap/processinfo/dc10c603-8e58-4611-baa3-44da2578d07a.json +0 -268
- package/.tap/processinfo/dde56c1a-858c-47cc-b0bb-61279620ac17.json +0 -268
- package/.tap/processinfo/e0d9c4ea-f7c7-4c64-8ced-66dc6f0ac5d2.json +0 -271
- package/.tap/processinfo/e121454f-5dfa-4209-ba15-4c39840871f2.json +0 -831
- package/.tap/processinfo/e1f43e40-c3fe-4eb8-a713-d5910cc6b25a.json +0 -268
- package/.tap/processinfo/e4575e7a-f00e-488b-94e1-8f877b54725e.json +0 -268
- package/.tap/processinfo/e9ad667e-8603-4488-af64-449cc9532803.json +0 -268
- package/.tap/processinfo/eb26a697-e5e2-4730-aeea-bcb9c49afd4d.json +0 -268
- package/.tap/processinfo/eb29d1c3-feaf-4744-9d84-cf257e8269b0.json +0 -268
- package/.tap/processinfo/ee720c0a-ed64-4e7e-8c0a-139c7b9725d2.json +0 -268
- package/.tap/processinfo/ef88c13a-87b2-49e4-a683-7b812505cd6f.json +0 -268
- package/.tap/processinfo/f4ed6948-dac0-4128-9f86-d083b6918ea7.json +0 -268
- package/.tap/processinfo/f7544c01-8ac7-4e42-8ad5-c4d62e094d1f.json +0 -270
- package/.tap/processinfo/f7cee4b3-7bcc-4591-a628-5629b0b41c9e.json +0 -268
- package/.tap/processinfo/f9c0a1f7-c1a4-44d3-ae3f-8c1eb42cd746.json +0 -269
- package/.tap/processinfo/fc46b4da-79db-4201-af7e-34bb17f92d69.json +0 -270
- package/.tap/processinfo/fccc0056-03c4-40cb-9d0b-2db4bbe573c1.json +0 -268
- package/.tap/processinfo/fd2df572-54d7-4ce7-b7aa-a2b4b00d4127.json +0 -254
- package/.tap/processinfo/fea9377f-b473-484d-bee6-ac7f49e50937.json +0 -269
- package/.tap/processinfo/feb516dc-abda-46e6-9b42-d37adfc63366.json +0 -268
- package/.tap/processinfo/ff0fda4c-aa2e-4236-906e-fdfb6bd6632e.json +0 -269
- package/.tap/test-results/test/404s.test.js.tap +0 -623
- package/.tap/test-results/test/500s.test.js.tap +0 -64
- package/.tap/test-results/test/allowUnsafeRegex.test.js.tap +0 -36
- package/.tap/test-results/test/als.test.js.tap +0 -15
- package/.tap/test-results/test/async-await.test.js.tap +0 -184
- package/.tap/test-results/test/async-dispose.test.js.tap +0 -8
- package/.tap/test-results/test/async_hooks.test.js.tap +0 -10
- package/.tap/test-results/test/bodyLimit.test.js.tap +0 -48
- package/.tap/test-results/test/buffer.test.js.tap +0 -20
- package/.tap/test-results/test/build/error-serializer.test.js.tap +0 -8
- package/.tap/test-results/test/build/version.test.js.tap +0 -7
- package/.tap/test-results/test/case-insensitive.test.js.tap +0 -36
- package/.tap/test-results/test/chainable.test.js.tap +0 -17
- package/.tap/test-results/test/check.test.js.tap +0 -10
- package/.tap/test-results/test/childLoggerFactory.test.js.tap +0 -23
- package/.tap/test-results/test/client-timeout.test.js.tap +0 -7
- package/.tap/test-results/test/close-pipelining.test.js.tap +0 -15
- package/.tap/test-results/test/close.test.js.tap +0 -172
- package/.tap/test-results/test/connectionTimeout.test.js.tap +0 -12
- package/.tap/test-results/test/constrained-routes.test.js.tap +0 -173
- package/.tap/test-results/test/content-length.test.js.tap +0 -46
- package/.tap/test-results/test/content-parser.test.js.tap +0 -266
- package/.tap/test-results/test/content-type.test.js.tap +0 -14
- package/.tap/test-results/test/context-config.test.js.tap +0 -41
- package/.tap/test-results/test/copy.test.js.tap +0 -14
- package/.tap/test-results/test/custom-http-server.test.js.tap +0 -30
- package/.tap/test-results/test/custom-parser-async.test.js.tap +0 -21
- package/.tap/test-results/test/custom-parser.0.test.js.tap +0 -199
- package/.tap/test-results/test/custom-parser.1.test.js.tap +0 -90
- package/.tap/test-results/test/custom-parser.2.test.js.tap +0 -22
- package/.tap/test-results/test/custom-parser.3.test.js.tap +0 -53
- package/.tap/test-results/test/custom-parser.4.test.js.tap +0 -45
- package/.tap/test-results/test/custom-parser.5.test.js.tap +0 -41
- package/.tap/test-results/test/custom-querystring-parser.test.js.tap +0 -46
- package/.tap/test-results/test/decorator.test.js.tap +0 -465
- package/.tap/test-results/test/delete.test.js.tap +0 -110
- package/.tap/test-results/test/diagnostics-channel/404.test.js.tap +0 -15
- package/.tap/test-results/test/diagnostics-channel/async-delay-request.test.js.tap +0 -25
- package/.tap/test-results/test/diagnostics-channel/async-request.test.js.tap +0 -24
- package/.tap/test-results/test/diagnostics-channel/error-before-handler.test.js.tap +0 -9
- package/.tap/test-results/test/diagnostics-channel/error-request.test.js.tap +0 -20
- package/.tap/test-results/test/diagnostics-channel/error-status.test.js.tap +0 -10
- package/.tap/test-results/test/diagnostics-channel/init.test.js.tap +0 -14
- package/.tap/test-results/test/diagnostics-channel/sync-delay-request.test.js.tap +0 -16
- package/.tap/test-results/test/diagnostics-channel/sync-request-reply.test.js.tap +0 -16
- package/.tap/test-results/test/diagnostics-channel/sync-request.test.js.tap +0 -19
- package/.tap/test-results/test/encapsulated-child-logger-factory.test.js.tap +0 -18
- package/.tap/test-results/test/encapsulated-error-handler.test.js.tap +0 -243
- package/.tap/test-results/test/esm/errorCodes.test.mjs.tap +0 -9
- package/.tap/test-results/test/esm/esm.test.mjs.tap +0 -8
- package/.tap/test-results/test/esm/index.test.js.tap +0 -8
- package/.tap/test-results/test/fastify-instance.test.js.tap +0 -114
- package/.tap/test-results/test/findRoute.test.js.tap +0 -37
- package/.tap/test-results/test/fluent-schema.test.js.tap +0 -36
- package/.tap/test-results/test/genReqId.test.js.tap +0 -106
- package/.tap/test-results/test/get.test.js.tap +0 -151
- package/.tap/test-results/test/handler-context.test.js.tap +0 -19
- package/.tap/test-results/test/has-route.test.js.tap +0 -30
- package/.tap/test-results/test/head.test.js.tap +0 -130
- package/.tap/test-results/test/header-overflow.test.js.tap +0 -16
- package/.tap/test-results/test/hooks-async.test.js.tap +0 -286
- package/.tap/test-results/test/hooks.on-listen.test.js.tap +0 -311
- package/.tap/test-results/test/hooks.on-ready.test.js.tap +0 -151
- package/.tap/test-results/test/hooks.test.js.tap +0 -966
- package/.tap/test-results/test/http2/closing.test.js.tap +0 -35
- package/.tap/test-results/test/http2/constraint.test.js.tap +0 -32
- package/.tap/test-results/test/http2/head.test.js.tap +0 -9
- package/.tap/test-results/test/http2/missing-http2-module.test.js.tap +0 -8
- package/.tap/test-results/test/http2/plain.test.js.tap +0 -22
- package/.tap/test-results/test/http2/secure-with-fallback.test.js.tap +0 -40
- package/.tap/test-results/test/http2/secure.test.js.tap +0 -27
- package/.tap/test-results/test/http2/unknown-http-method.test.js.tap +0 -9
- package/.tap/test-results/test/https/custom-https-server.test.js.tap +0 -10
- package/.tap/test-results/test/https/https.test.js.tap +0 -45
- package/.tap/test-results/test/imports.test.js.tap +0 -14
- package/.tap/test-results/test/inject.test.js.tap +0 -165
- package/.tap/test-results/test/internals/all.test.js.tap +0 -42
- package/.tap/test-results/test/internals/contentTypeParser.test.js.tap +0 -14
- package/.tap/test-results/test/internals/context.test.js.tap +0 -14
- package/.tap/test-results/test/internals/decorator.test.js.tap +0 -51
- package/.tap/test-results/test/internals/errors.test.js.tap +0 -1212
- package/.tap/test-results/test/internals/handleRequest.test.js.tap +0 -69
- package/.tap/test-results/test/internals/hookRunner.test.js.tap +0 -143
- package/.tap/test-results/test/internals/hooks.test.js.tap +0 -45
- package/.tap/test-results/test/internals/initialConfig.test.js.tap +0 -125
- package/.tap/test-results/test/internals/logger.test.js.tap +0 -71
- package/.tap/test-results/test/internals/plugin.test.js.tap +0 -48
- package/.tap/test-results/test/internals/reply-serialize.test.js.tap +0 -166
- package/.tap/test-results/test/internals/reply.test.js.tap +0 -688
- package/.tap/test-results/test/internals/reqIdGenFactory.test.js.tap +0 -74
- package/.tap/test-results/test/internals/request-validate.test.js.tap +0 -384
- package/.tap/test-results/test/internals/request.test.js.tap +0 -163
- package/.tap/test-results/test/internals/server.test.js.tap +0 -30
- package/.tap/test-results/test/internals/validation.test.js.tap +0 -121
- package/.tap/test-results/test/keepAliveTimeout.test.js.tap +0 -12
- package/.tap/test-results/test/listen.1.test.js.tap +0 -31
- package/.tap/test-results/test/listen.2.test.js.tap +0 -46
- package/.tap/test-results/test/listen.3.test.js.tap +0 -25
- package/.tap/test-results/test/listen.4.test.js.tap +0 -51
- package/.tap/test-results/test/lock.test.js.tap +0 -29
- package/.tap/test-results/test/logger/instantiation.test.js.tap +0 -92
- package/.tap/test-results/test/logger/logging.test.js.tap +0 -117
- package/.tap/test-results/test/logger/options.test.js.tap +0 -165
- package/.tap/test-results/test/logger/request.test.js.tap +0 -82
- package/.tap/test-results/test/logger/response.test.js.tap +0 -38
- package/.tap/test-results/test/maxRequestsPerSocket.test.js.tap +0 -44
- package/.tap/test-results/test/method-missing.test.js.tap +0 -8
- package/.tap/test-results/test/middleware.test.js.tap +0 -17
- package/.tap/test-results/test/mkcalendar.test.js.tap +0 -43
- package/.tap/test-results/test/mkcol.test.js.tap +0 -14
- package/.tap/test-results/test/move.test.js.tap +0 -15
- package/.tap/test-results/test/noop-set.test.js.tap +0 -8
- package/.tap/test-results/test/nullable-validation.test.js.tap +0 -36
- package/.tap/test-results/test/options.error-handler.test.js.tap +0 -186
- package/.tap/test-results/test/options.test.js.tap +0 -174
- package/.tap/test-results/test/output-validation.test.js.tap +0 -66
- package/.tap/test-results/test/patch.error-handler.test.js.tap +0 -206
- package/.tap/test-results/test/patch.test.js.tap +0 -182
- package/.tap/test-results/test/plugin.1.test.js.tap +0 -78
- package/.tap/test-results/test/plugin.2.test.js.tap +0 -102
- package/.tap/test-results/test/plugin.3.test.js.tap +0 -58
- package/.tap/test-results/test/plugin.4.test.js.tap +0 -164
- package/.tap/test-results/test/post-empty-body.test.js.tap +0 -8
- package/.tap/test-results/test/pretty-print.test.js.tap +0 -82
- package/.tap/test-results/test/promises.test.js.tap +0 -46
- package/.tap/test-results/test/propfind.test.js.tap +0 -43
- package/.tap/test-results/test/proppatch.test.js.tap +0 -29
- package/.tap/test-results/test/proto-poisoning.test.js.tap +0 -47
- package/.tap/test-results/test/put.error-handler.test.js.tap +0 -206
- package/.tap/test-results/test/put.test.js.tap +0 -182
- package/.tap/test-results/test/register.test.js.tap +0 -61
- package/.tap/test-results/test/reply-code.test.js.tap +0 -40
- package/.tap/test-results/test/reply-earlyHints.test.js.tap +0 -22
- package/.tap/test-results/test/reply-error.test.js.tap +0 -643
- package/.tap/test-results/test/reply-trailers.test.js.tap +0 -176
- package/.tap/test-results/test/report.test.js.tap +0 -43
- package/.tap/test-results/test/request-error.test.js.tap +0 -98
- package/.tap/test-results/test/request-id.test.js.tap +0 -38
- package/.tap/test-results/test/request.deprecated.test.js.tap +0 -13
- package/.tap/test-results/test/requestTimeout.test.js.tap +0 -21
- package/.tap/test-results/test/route-hooks.test.js.tap +0 -498
- package/.tap/test-results/test/route-prefix.test.js.tap +0 -195
- package/.tap/test-results/test/route-shorthand.test.js.tap +0 -190
- package/.tap/test-results/test/route.1.test.js.tap +0 -93
- package/.tap/test-results/test/route.2.test.js.tap +0 -28
- package/.tap/test-results/test/route.3.test.js.tap +0 -39
- package/.tap/test-results/test/route.4.test.js.tap +0 -32
- package/.tap/test-results/test/route.5.test.js.tap +0 -54
- package/.tap/test-results/test/route.6.test.js.tap +0 -81
- package/.tap/test-results/test/route.7.test.js.tap +0 -93
- package/.tap/test-results/test/route.8.test.js.tap +0 -38
- package/.tap/test-results/test/router-options.test.js.tap +0 -104
- package/.tap/test-results/test/same-shape.test.js.tap +0 -22
- package/.tap/test-results/test/schema-examples.test.js.tap +0 -85
- package/.tap/test-results/test/schema-feature.test.js.tap +0 -445
- package/.tap/test-results/test/schema-serialization.test.js.tap +0 -194
- package/.tap/test-results/test/schema-special-usage.test.js.tap +0 -186
- package/.tap/test-results/test/schema-validation.test.js.tap +0 -199
- package/.tap/test-results/test/search.test.js.tap +0 -77
- package/.tap/test-results/test/serialize-response.test.js.tap +0 -26
- package/.tap/test-results/test/server.test.js.tap +0 -65
- package/.tap/test-results/test/set-error-handler.test.js.tap +0 -7
- package/.tap/test-results/test/skip-reply-send.test.js.tap +0 -272
- package/.tap/test-results/test/stream.1.test.js.tap +0 -36
- package/.tap/test-results/test/stream.2.test.js.tap +0 -20
- package/.tap/test-results/test/stream.3.test.js.tap +0 -34
- package/.tap/test-results/test/stream.4.test.js.tap +0 -40
- package/.tap/test-results/test/stream.5.test.js.tap +0 -37
- package/.tap/test-results/test/sync-routes.test.js.tap +0 -19
- package/.tap/test-results/test/throw.test.js.tap +0 -116
- package/.tap/test-results/test/trace.test.js.tap +0 -7
- package/.tap/test-results/test/trust-proxy.test.js.tap +0 -109
- package/.tap/test-results/test/type-provider.test.js.tap +0 -12
- package/.tap/test-results/test/unlock.test.js.tap +0 -14
- package/.tap/test-results/test/upgrade.test.js.tap +0 -8
- package/.tap/test-results/test/url-rewriting.test.js.tap +0 -39
- package/.tap/test-results/test/useSemicolonDelimiter.test.js.tap +0 -33
- package/.tap/test-results/test/validation-error-handling.test.js.tap +0 -180
- package/.tap/test-results/test/versioned-routes.test.js.tap +0 -151
- package/.tap/test-results/test/web-api.test.js.tap +0 -51
- package/.tap/test-results/test/wrapThenable.test.js.tap +0 -11
- package/EXPENSE_POLICY.md +0 -105
- package/test/types/import.js +0 -2
package/SPONSORS.md
CHANGED
|
@@ -14,6 +14,8 @@ _Be the first!_
|
|
|
14
14
|
## Tier 3
|
|
15
15
|
|
|
16
16
|
- [Mercedes-Benz Group](https://github.com/mercedes-benz)
|
|
17
|
+
- [Val Town, Inc.](https://opencollective.com/valtown)
|
|
18
|
+
- [Handsontable - JavaScript Data Grid](https://handsontable.com/docs/react-data-grid/?utm_source=Fastify_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024)
|
|
17
19
|
|
|
18
20
|
## Tier 2
|
|
19
21
|
|
|
@@ -6,6 +6,34 @@ Before migrating to v4, please ensure that you have fixed all deprecation
|
|
|
6
6
|
warnings from v3. All v3 deprecations have been removed and they will no longer
|
|
7
7
|
work after upgrading.
|
|
8
8
|
|
|
9
|
+
## Codemods
|
|
10
|
+
### Fastify v4 Codemods
|
|
11
|
+
|
|
12
|
+
To help with the upgrade, we’ve worked with the team at
|
|
13
|
+
[Codemod](https://github.com/codemod-com/codemod) to
|
|
14
|
+
publish codemods that will automatically update your code to many of
|
|
15
|
+
the new APIs and patterns in Fastify v4.
|
|
16
|
+
|
|
17
|
+
Run the following
|
|
18
|
+
[migration recipe](https://go.codemod.com/fastify-4-migration-recipe) to
|
|
19
|
+
automatically update your code to Fastify v4:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
npx codemod@latest fastify/4/migration-recipe
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This will run the following codemods:
|
|
26
|
+
|
|
27
|
+
- [`fastify/4/remove-app-use`](https://go.codemod.com/fastify-4-remove-app-use)
|
|
28
|
+
- [`fastify/4/reply-raw-access`](https://go.codemod.com/fastify-4-reply-raw-access)
|
|
29
|
+
- [`fastify/4/wrap-routes-plugin`](https://go.codemod.com/fastify-4-wrap-routes-plugin)
|
|
30
|
+
- [`fastify/4/await-register-calls`](https://go.codemod.com/fastify-4-await-register-calls)
|
|
31
|
+
|
|
32
|
+
Each of these codemods automates the changes listed in the v4 migration guide.
|
|
33
|
+
For a complete list of available Fastify codemods and further details,
|
|
34
|
+
see [Codemod Registry](https://go.codemod.com/fastify).
|
|
35
|
+
|
|
36
|
+
|
|
9
37
|
## Breaking Changes
|
|
10
38
|
|
|
11
39
|
### Error handling composition ([#3261](https://github.com/fastify/fastify/pull/3261))
|
|
@@ -55,11 +83,23 @@ If you need to use middleware, use
|
|
|
55
83
|
continue to be maintained.
|
|
56
84
|
However, it is strongly recommended that you migrate to Fastify's [hooks](../Reference/Hooks.md).
|
|
57
85
|
|
|
86
|
+
> **Note**: Codemod remove `app.use()` with:
|
|
87
|
+
>
|
|
88
|
+
> ```bash
|
|
89
|
+
> npx codemod@latest fastify/4/remove-app-use
|
|
90
|
+
> ```
|
|
91
|
+
|
|
58
92
|
### `reply.res` moved to `reply.raw`
|
|
59
93
|
|
|
60
94
|
If you previously used the `reply.res` attribute to access the underlying Request
|
|
61
95
|
object you will now need to use `reply.raw`.
|
|
62
96
|
|
|
97
|
+
> **Note**: Codemod `reply.res` to `reply.raw` with:
|
|
98
|
+
>
|
|
99
|
+
> ```bash
|
|
100
|
+
> npx codemod@latest fastify/4/reply-raw-access
|
|
101
|
+
> ```
|
|
102
|
+
|
|
63
103
|
### Need to `return reply` to signal a "fork" of the promise chain
|
|
64
104
|
|
|
65
105
|
In some situations, like when a response is sent asynchronously or when you are
|
|
@@ -105,6 +145,11 @@ As a result, if you specify an `onRoute` hook in a plugin you should now either:
|
|
|
105
145
|
done();
|
|
106
146
|
});
|
|
107
147
|
```
|
|
148
|
+
> **Note**: Codemod synchronous route definitions with:
|
|
149
|
+
>
|
|
150
|
+
> ```bash
|
|
151
|
+
> npx codemod@latest fastify/4/wrap-routes-plugin
|
|
152
|
+
> ```
|
|
108
153
|
|
|
109
154
|
* use `await register(...)`
|
|
110
155
|
|
|
@@ -130,6 +175,13 @@ As a result, if you specify an `onRoute` hook in a plugin you should now either:
|
|
|
130
175
|
});
|
|
131
176
|
```
|
|
132
177
|
|
|
178
|
+
> **Note**: Codemod 'await register(...)' with:
|
|
179
|
+
>
|
|
180
|
+
> ```bash
|
|
181
|
+
> npx codemod@latest fastify/4/await-register-calls
|
|
182
|
+
> ```
|
|
183
|
+
|
|
184
|
+
|
|
133
185
|
### Optional URL parameters
|
|
134
186
|
|
|
135
187
|
If you've already used any implicitly optional parameters, you'll get a 404
|
package/docs/Reference/Routes.md
CHANGED
|
@@ -43,7 +43,8 @@ fastify.route(options)
|
|
|
43
43
|
[here](./Validation-and-Serialization.md) for more info.
|
|
44
44
|
|
|
45
45
|
* `body`: validates the body of the request if it is a POST, PUT, PATCH,
|
|
46
|
-
TRACE, SEARCH, PROPFIND, PROPPATCH
|
|
46
|
+
TRACE, SEARCH, PROPFIND, PROPPATCH, COPY, MOVE, MKCOL, REPORT, MKCALENDAR
|
|
47
|
+
or LOCK method.
|
|
47
48
|
* `querystring` or `query`: validates the querystring. This can be a complete
|
|
48
49
|
JSON Schema object, with the property `type` of `object` and `properties`
|
|
49
50
|
object of parameters, or simply the values of what would be contained in the
|
package/docs/Reference/Server.md
CHANGED
|
@@ -272,6 +272,8 @@ fastify.get('///foo//bar//', function (req, reply) {
|
|
|
272
272
|
### `maxParamLength`
|
|
273
273
|
<a id="factory-max-param-length"></a>
|
|
274
274
|
|
|
275
|
+
+ Default: `100`
|
|
276
|
+
|
|
275
277
|
You can set a custom length for parameters in parametric (standard, regex, and
|
|
276
278
|
multi) routes by using `maxParamLength` option; the default value is 100
|
|
277
279
|
characters. If the maximum length limit is reached, the not found route will
|
|
@@ -235,6 +235,28 @@ const schema = {
|
|
|
235
235
|
fastify.post('/the/url', { schema }, handler)
|
|
236
236
|
```
|
|
237
237
|
|
|
238
|
+
For `body` schema, it is further possible to differentiate the schema per content
|
|
239
|
+
type by nesting the schemas inside `content` property. The schema validation
|
|
240
|
+
will be applied based on the `Content-Type` header in the request.
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
fastify.post('/the/url', {
|
|
244
|
+
schema: {
|
|
245
|
+
body: {
|
|
246
|
+
content: {
|
|
247
|
+
'application/json': {
|
|
248
|
+
schema: { type: 'object' }
|
|
249
|
+
},
|
|
250
|
+
'text/plain': {
|
|
251
|
+
schema: { type: 'string' }
|
|
252
|
+
}
|
|
253
|
+
// Other content types will not be validated
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}, handler)
|
|
258
|
+
```
|
|
259
|
+
|
|
238
260
|
*Note that Ajv will try to [coerce](https://ajv.js.org/coercion.html) the values
|
|
239
261
|
to the types specified in your schema `type` keywords, both to pass the
|
|
240
262
|
validation and to use the correctly typed data afterwards.*
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
- [FSTDEP019](#FSTDEP019)
|
|
26
26
|
- [FSTDEP020](#FSTDEP020)
|
|
27
27
|
- [FSTDEP021](#FSTDEP021)
|
|
28
|
+
- [FSTDEP022](#FSTDEP022)
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
## Warnings
|
|
@@ -92,3 +93,4 @@ Deprecation codes are further supported by the Node.js CLI options:
|
|
|
92
93
|
| <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) |
|
|
93
94
|
| <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) |
|
|
94
95
|
| <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) |
|
|
96
|
+
| <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) |
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '4.
|
|
3
|
+
const VERSION = '4.29.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('node:http')
|
|
@@ -671,7 +671,7 @@ function fastify (options) {
|
|
|
671
671
|
}
|
|
672
672
|
|
|
673
673
|
if (name === 'onClose') {
|
|
674
|
-
this.onClose(fn)
|
|
674
|
+
this.onClose(fn.bind(this))
|
|
675
675
|
} else if (name === 'onReady' || name === 'onListen' || name === 'onRoute') {
|
|
676
676
|
this[kHooks].add(name, fn)
|
|
677
677
|
} else {
|
package/lib/handleRequest.js
CHANGED
|
@@ -28,7 +28,8 @@ function handleRequest (err, request, reply) {
|
|
|
28
28
|
const contentType = headers['content-type']
|
|
29
29
|
|
|
30
30
|
if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE' || method === 'SEARCH' ||
|
|
31
|
-
method === 'PROPFIND' || method === 'PROPPATCH' || method === 'LOCK' || method === '
|
|
31
|
+
method === 'PROPFIND' || method === 'PROPPATCH' || method === 'LOCK' || method === 'COPY' || method === 'MOVE' ||
|
|
32
|
+
method === 'MKCOL' || method === 'REPORT' || method === 'MKCALENDAR') {
|
|
32
33
|
if (contentType === undefined) {
|
|
33
34
|
if (
|
|
34
35
|
headers['transfer-encoding'] === undefined &&
|
package/lib/reply.js
CHANGED
|
@@ -602,14 +602,30 @@ function onSendEnd (reply, payload) {
|
|
|
602
602
|
reply.header('Trailer', header.trim())
|
|
603
603
|
}
|
|
604
604
|
|
|
605
|
-
// since Response contain status code,
|
|
606
|
-
//
|
|
607
|
-
|
|
608
|
-
if (
|
|
605
|
+
// since Response contain status code, headers and body,
|
|
606
|
+
// we need to update the status, add the headers and use it's body as payload
|
|
607
|
+
// before continuing
|
|
608
|
+
if (toString.call(payload) === '[object Response]') {
|
|
609
609
|
// https://developer.mozilla.org/en-US/docs/Web/API/Response/status
|
|
610
610
|
if (typeof payload.status === 'number') {
|
|
611
611
|
reply.code(payload.status)
|
|
612
612
|
}
|
|
613
|
+
|
|
614
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Response/headers
|
|
615
|
+
if (typeof payload.headers === 'object' && typeof payload.headers.forEach === 'function') {
|
|
616
|
+
for (const [headerName, headerValue] of payload.headers) {
|
|
617
|
+
reply.header(headerName, headerValue)
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Response/body
|
|
622
|
+
if (payload.body !== null) {
|
|
623
|
+
if (payload.bodyUsed) {
|
|
624
|
+
throw new FST_ERR_REP_RESPONSE_BODY_CONSUMED()
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
// Keep going, body is either null or ReadableStream
|
|
628
|
+
payload = payload.body
|
|
613
629
|
}
|
|
614
630
|
const statusCode = res.statusCode
|
|
615
631
|
|
|
@@ -656,26 +672,6 @@ function onSendEnd (reply, payload) {
|
|
|
656
672
|
return
|
|
657
673
|
}
|
|
658
674
|
|
|
659
|
-
// Response
|
|
660
|
-
if (isResponse) {
|
|
661
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Response/headers
|
|
662
|
-
if (typeof payload.headers === 'object' && typeof payload.headers.forEach === 'function') {
|
|
663
|
-
for (const [headerName, headerValue] of payload.headers) {
|
|
664
|
-
reply.header(headerName, headerValue)
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Response/body
|
|
669
|
-
if (payload.body != null) {
|
|
670
|
-
if (payload.bodyUsed) {
|
|
671
|
-
throw new FST_ERR_REP_RESPONSE_BODY_CONSUMED()
|
|
672
|
-
}
|
|
673
|
-
// Response.body always a ReadableStream
|
|
674
|
-
sendWebStream(payload.body, res, reply)
|
|
675
|
-
}
|
|
676
|
-
return
|
|
677
|
-
}
|
|
678
|
-
|
|
679
675
|
if (typeof payload !== 'string' && !Buffer.isBuffer(payload)) {
|
|
680
676
|
throw new FST_ERR_REP_INVALID_PAYLOAD_TYPE(typeof payload)
|
|
681
677
|
}
|
|
@@ -726,7 +722,7 @@ function sendStream (payload, res, reply) {
|
|
|
726
722
|
if (res.headersSent || reply.request.raw.aborted === true) {
|
|
727
723
|
if (!errorLogged) {
|
|
728
724
|
errorLogged = true
|
|
729
|
-
logStreamError(reply.log, err,
|
|
725
|
+
logStreamError(reply.log, err, reply)
|
|
730
726
|
}
|
|
731
727
|
res.destroy()
|
|
732
728
|
} else {
|
package/lib/route.js
CHANGED
|
@@ -366,7 +366,7 @@ function buildRouting (options) {
|
|
|
366
366
|
// any route insertion error created by fastify can be safely ignore
|
|
367
367
|
// because it only duplicate route for head
|
|
368
368
|
if (!context[kRouteByFastify]) {
|
|
369
|
-
const isDuplicatedRoute = error.message.includes(`Method '${opts.method}' already declared for route
|
|
369
|
+
const isDuplicatedRoute = error.message.includes(`Method '${opts.method}' already declared for route`)
|
|
370
370
|
if (isDuplicatedRoute) {
|
|
371
371
|
throw new FST_ERR_DUPLICATED_ROUTE(opts.method, opts.url)
|
|
372
372
|
}
|
|
@@ -407,7 +407,7 @@ function buildRouting (options) {
|
|
|
407
407
|
fourOhFour.setContext(this, context)
|
|
408
408
|
|
|
409
409
|
if (opts.schema) {
|
|
410
|
-
context.schema = normalizeSchema(context.schema, this.initialConfig)
|
|
410
|
+
context.schema = normalizeSchema(opts, context.schema, this.initialConfig)
|
|
411
411
|
|
|
412
412
|
const schemaController = this[kSchemaController]
|
|
413
413
|
if (!opts.validatorCompiler && (opts.schema.body || opts.schema.headers || opts.schema.querystring || opts.schema.params)) {
|
package/lib/schemas.js
CHANGED
|
@@ -4,6 +4,9 @@ const fastClone = require('rfdc')({ circles: false, proto: true })
|
|
|
4
4
|
const { kSchemaVisited, kSchemaResponse } = require('./symbols')
|
|
5
5
|
const kFluentSchema = Symbol.for('fluent-schema-object')
|
|
6
6
|
|
|
7
|
+
const {
|
|
8
|
+
FSTDEP022
|
|
9
|
+
} = require('./warnings')
|
|
7
10
|
const {
|
|
8
11
|
FST_ERR_SCH_MISSING_ID,
|
|
9
12
|
FST_ERR_SCH_ALREADY_PRESENT,
|
|
@@ -54,7 +57,7 @@ function isCustomSchemaPrototype (schema) {
|
|
|
54
57
|
return typeof schema === 'object' && Object.getPrototypeOf(schema) !== Object.prototype
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
function normalizeSchema (routeSchemas, serverOptions) {
|
|
60
|
+
function normalizeSchema (opts, routeSchemas, serverOptions) {
|
|
58
61
|
if (routeSchemas[kSchemaVisited]) {
|
|
59
62
|
return routeSchemas
|
|
60
63
|
}
|
|
@@ -73,7 +76,20 @@ function normalizeSchema (routeSchemas, serverOptions) {
|
|
|
73
76
|
for (const key of SCHEMAS_SOURCE) {
|
|
74
77
|
const schema = routeSchemas[key]
|
|
75
78
|
if (schema && !isCustomSchemaPrototype(schema)) {
|
|
76
|
-
|
|
79
|
+
if (key === 'body' && schema.content) {
|
|
80
|
+
const contentProperty = schema.content
|
|
81
|
+
const keys = Object.keys(contentProperty)
|
|
82
|
+
for (let i = 0; i < keys.length; i++) {
|
|
83
|
+
const contentType = keys[i]
|
|
84
|
+
const contentSchema = contentProperty[contentType].schema
|
|
85
|
+
if (!contentSchema) {
|
|
86
|
+
throw new FST_ERR_SCH_CONTENT_MISSING_SCHEMA(contentType)
|
|
87
|
+
}
|
|
88
|
+
routeSchemas.body.content[contentType].schema = getSchemaAnyway(opts.url, contentSchema, serverOptions.jsonShorthand)
|
|
89
|
+
}
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
routeSchemas[key] = getSchemaAnyway(opts.url, schema, serverOptions.jsonShorthand)
|
|
77
93
|
}
|
|
78
94
|
}
|
|
79
95
|
|
|
@@ -95,7 +111,7 @@ function normalizeSchema (routeSchemas, serverOptions) {
|
|
|
95
111
|
if (keys.length === 1) { break }
|
|
96
112
|
throw new FST_ERR_SCH_CONTENT_MISSING_SCHEMA(mediaName)
|
|
97
113
|
}
|
|
98
|
-
routeSchemas.response[code].content[mediaName].schema = getSchemaAnyway(contentProperty[mediaName].schema, serverOptions.jsonShorthand)
|
|
114
|
+
routeSchemas.response[code].content[mediaName].schema = getSchemaAnyway(opts.url, contentProperty[mediaName].schema, serverOptions.jsonShorthand)
|
|
99
115
|
if (i === keys.length - 1) {
|
|
100
116
|
hasContentMultipleContentTypes = true
|
|
101
117
|
}
|
|
@@ -103,7 +119,7 @@ function normalizeSchema (routeSchemas, serverOptions) {
|
|
|
103
119
|
}
|
|
104
120
|
|
|
105
121
|
if (!hasContentMultipleContentTypes) {
|
|
106
|
-
routeSchemas.response[code] = getSchemaAnyway(routeSchemas.response[code], serverOptions.jsonShorthand)
|
|
122
|
+
routeSchemas.response[code] = getSchemaAnyway(opts.url, routeSchemas.response[code], serverOptions.jsonShorthand)
|
|
107
123
|
}
|
|
108
124
|
}
|
|
109
125
|
}
|
|
@@ -129,9 +145,10 @@ function generateFluentSchema (schema) {
|
|
|
129
145
|
}
|
|
130
146
|
}
|
|
131
147
|
|
|
132
|
-
function getSchemaAnyway (schema, jsonShorthand) {
|
|
148
|
+
function getSchemaAnyway (url, schema, jsonShorthand) {
|
|
133
149
|
if (!jsonShorthand || schema.$ref || schema.oneOf || schema.allOf || schema.anyOf || schema.$merge || schema.$patch) return schema
|
|
134
150
|
if (!schema.type && !schema.properties) {
|
|
151
|
+
FSTDEP022(url)
|
|
135
152
|
return {
|
|
136
153
|
type: 'object',
|
|
137
154
|
properties: schema
|
package/lib/server.js
CHANGED
|
@@ -72,7 +72,8 @@ function createServer (options, httpHandler) {
|
|
|
72
72
|
} else {
|
|
73
73
|
host = listenOptions.host
|
|
74
74
|
}
|
|
75
|
-
if (Object.prototype.hasOwnProperty.call(listenOptions, 'host') === false
|
|
75
|
+
if (Object.prototype.hasOwnProperty.call(listenOptions, 'host') === false ||
|
|
76
|
+
listenOptions.host == null) {
|
|
76
77
|
listenOptions.host = host
|
|
77
78
|
}
|
|
78
79
|
if (host === 'localhost') {
|
|
@@ -220,6 +221,7 @@ function multipleBindings (mainServer, httpHandler, serverOpts, listenOptions, o
|
|
|
220
221
|
function listenCallback (server, listenOptions) {
|
|
221
222
|
const wrap = (err) => {
|
|
222
223
|
server.removeListener('error', wrap)
|
|
224
|
+
server.removeListener('listening', wrap)
|
|
223
225
|
if (!err) {
|
|
224
226
|
const address = logServerAddress.call(this, server, listenOptions.listenTextResolver || defaultResolveServerListeningText)
|
|
225
227
|
listenOptions.cb(null, address)
|
|
@@ -240,7 +242,8 @@ function listenCallback (server, listenOptions) {
|
|
|
240
242
|
|
|
241
243
|
server.once('error', wrap)
|
|
242
244
|
if (!this[kState].closing) {
|
|
243
|
-
server.
|
|
245
|
+
server.once('listening', wrap)
|
|
246
|
+
server.listen(listenOptions)
|
|
244
247
|
this[kState].listening = true
|
|
245
248
|
}
|
|
246
249
|
}
|
|
@@ -255,25 +258,33 @@ function listenPromise (server, listenOptions) {
|
|
|
255
258
|
|
|
256
259
|
return this.ready().then(() => {
|
|
257
260
|
let errEventHandler
|
|
261
|
+
let listeningEventHandler
|
|
262
|
+
function cleanup () {
|
|
263
|
+
server.removeListener('error', errEventHandler)
|
|
264
|
+
server.removeListener('listening', listeningEventHandler)
|
|
265
|
+
}
|
|
258
266
|
const errEvent = new Promise((resolve, reject) => {
|
|
259
267
|
errEventHandler = (err) => {
|
|
268
|
+
cleanup()
|
|
260
269
|
this[kState].listening = false
|
|
261
270
|
reject(err)
|
|
262
271
|
}
|
|
263
272
|
server.once('error', errEventHandler)
|
|
264
273
|
})
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
274
|
+
const listeningEvent = new Promise((resolve, reject) => {
|
|
275
|
+
listeningEventHandler = () => {
|
|
276
|
+
cleanup()
|
|
277
|
+
this[kState].listening = true
|
|
268
278
|
resolve(logServerAddress.call(this, server, listenOptions.listenTextResolver || defaultResolveServerListeningText))
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
this[kState].listening = true
|
|
279
|
+
}
|
|
280
|
+
server.once('listening', listeningEventHandler)
|
|
272
281
|
})
|
|
273
282
|
|
|
283
|
+
server.listen(listenOptions)
|
|
284
|
+
|
|
274
285
|
return Promise.race([
|
|
275
286
|
errEvent, // e.g invalid port range error is always emitted before the server listening
|
|
276
|
-
|
|
287
|
+
listeningEvent
|
|
277
288
|
])
|
|
278
289
|
})
|
|
279
290
|
}
|
package/lib/validation.js
CHANGED
|
@@ -87,7 +87,17 @@ function compileSchemasForValidation (context, compile, isCustom) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
if (schema.body) {
|
|
90
|
-
|
|
90
|
+
const contentProperty = schema.body.content
|
|
91
|
+
if (contentProperty) {
|
|
92
|
+
const contentTypeSchemas = {}
|
|
93
|
+
for (const contentType of Object.keys(contentProperty)) {
|
|
94
|
+
const contentSchema = contentProperty[contentType].schema
|
|
95
|
+
contentTypeSchemas[contentType] = compile({ schema: contentSchema, method, url, httpPart: 'body', contentType })
|
|
96
|
+
}
|
|
97
|
+
context[bodySchema] = contentTypeSchemas
|
|
98
|
+
} else {
|
|
99
|
+
context[bodySchema] = compile({ schema: schema.body, method, url, httpPart: 'body' })
|
|
100
|
+
}
|
|
91
101
|
} else if (Object.prototype.hasOwnProperty.call(schema, 'body')) {
|
|
92
102
|
FSTWRN001('body', method, url)
|
|
93
103
|
}
|
|
@@ -140,7 +150,18 @@ function validate (context, request, execution) {
|
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
if (runExecution || !execution.skipBody) {
|
|
143
|
-
|
|
153
|
+
let validatorFunction = null
|
|
154
|
+
if (typeof context[bodySchema] === 'function') {
|
|
155
|
+
validatorFunction = context[bodySchema]
|
|
156
|
+
} else if (context[bodySchema]) {
|
|
157
|
+
// TODO: add request.contentType and reuse it here
|
|
158
|
+
const contentType = request.headers['content-type']?.split(';', 1)[0]
|
|
159
|
+
const contentSchema = context[bodySchema][contentType]
|
|
160
|
+
if (contentSchema) {
|
|
161
|
+
validatorFunction = contentSchema
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const body = validateParam(validatorFunction, request, 'body')
|
|
144
165
|
if (body) {
|
|
145
166
|
if (typeof body.then !== 'function') {
|
|
146
167
|
return wrapValidationError(body, 'body', context.schemaErrorFormatter)
|
package/lib/warnings.js
CHANGED
|
@@ -87,6 +87,11 @@ const FSTDEP021 = createDeprecation({
|
|
|
87
87
|
message: 'The `reply.redirect()` method has a new signature: `reply.redirect(url: string, code?: number)`. It will be enforced in `fastify@v5`'
|
|
88
88
|
})
|
|
89
89
|
|
|
90
|
+
const FSTDEP022 = createDeprecation({
|
|
91
|
+
code: 'FSTDEP021',
|
|
92
|
+
message: 'You are using the deprecated json shorthand schema on route %s. Specify full object schema instead. It will be removed in `fastify@v5`'
|
|
93
|
+
})
|
|
94
|
+
|
|
90
95
|
const FSTWRN001 = createWarning({
|
|
91
96
|
name: 'FastifyWarning',
|
|
92
97
|
code: 'FSTWRN001',
|
|
@@ -119,6 +124,7 @@ module.exports = {
|
|
|
119
124
|
FSTDEP019,
|
|
120
125
|
FSTDEP020,
|
|
121
126
|
FSTDEP021,
|
|
127
|
+
FSTDEP022,
|
|
122
128
|
FSTWRN001,
|
|
123
129
|
FSTWRN002
|
|
124
130
|
}
|
package/package.json
CHANGED
package/test/close.test.js
CHANGED
|
@@ -10,11 +10,14 @@ const split = require('split2')
|
|
|
10
10
|
const { sleep } = require('./helper')
|
|
11
11
|
|
|
12
12
|
test('close callback', t => {
|
|
13
|
-
t.plan(
|
|
13
|
+
t.plan(7)
|
|
14
14
|
const fastify = Fastify()
|
|
15
15
|
fastify.addHook('onClose', onClose)
|
|
16
16
|
function onClose (instance, done) {
|
|
17
|
+
t.type(fastify, this)
|
|
17
18
|
t.type(fastify, instance)
|
|
19
|
+
t.equal(fastify, this)
|
|
20
|
+
t.equal(fastify, instance)
|
|
18
21
|
done()
|
|
19
22
|
}
|
|
20
23
|
|
package/test/copy.test.js
CHANGED
|
@@ -12,7 +12,10 @@ test('can be created - copy', t => {
|
|
|
12
12
|
method: 'COPY',
|
|
13
13
|
url: '*',
|
|
14
14
|
handler: function (req, reply) {
|
|
15
|
-
reply.code(204)
|
|
15
|
+
reply.code(204)
|
|
16
|
+
.header('location', req.headers.destination)
|
|
17
|
+
.header('body', req.body.toString())
|
|
18
|
+
.send()
|
|
16
19
|
}
|
|
17
20
|
})
|
|
18
21
|
t.pass()
|
|
@@ -26,15 +29,19 @@ fastify.listen({ port: 0 }, err => {
|
|
|
26
29
|
t.teardown(() => { fastify.close() })
|
|
27
30
|
|
|
28
31
|
test('request - copy', t => {
|
|
29
|
-
t.plan(
|
|
32
|
+
t.plan(4)
|
|
30
33
|
sget({
|
|
31
34
|
url: `http://localhost:${fastify.server.address().port}/test.txt`,
|
|
32
35
|
method: 'COPY',
|
|
33
36
|
headers: {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
destination: '/test2.txt',
|
|
38
|
+
'Content-Type': 'text/plain'
|
|
39
|
+
},
|
|
40
|
+
body: '/test3.txt'
|
|
41
|
+
}, (err, response) => {
|
|
37
42
|
t.error(err)
|
|
43
|
+
t.equal(response.headers.location, '/test2.txt')
|
|
44
|
+
t.equal(response.headers.body, '/test3.txt')
|
|
38
45
|
t.equal(response.statusCode, 204)
|
|
39
46
|
})
|
|
40
47
|
})
|
|
@@ -63,7 +63,7 @@ test('build schema - output schema', t => {
|
|
|
63
63
|
t.equal(typeof opts[symbols.responseSchema]['201'], 'function')
|
|
64
64
|
})
|
|
65
65
|
|
|
66
|
-
test('build schema -
|
|
66
|
+
test('build schema - body schema', t => {
|
|
67
67
|
t.plan(1)
|
|
68
68
|
const opts = {
|
|
69
69
|
schema: {
|
|
@@ -79,6 +79,32 @@ test('build schema - payload schema', t => {
|
|
|
79
79
|
t.equal(typeof opts[symbols.bodySchema], 'function')
|
|
80
80
|
})
|
|
81
81
|
|
|
82
|
+
test('build schema - body with multiple content type schemas', t => {
|
|
83
|
+
t.plan(2)
|
|
84
|
+
const opts = {
|
|
85
|
+
schema: {
|
|
86
|
+
body: {
|
|
87
|
+
content: {
|
|
88
|
+
'application/json': {
|
|
89
|
+
schema: {
|
|
90
|
+
type: 'object',
|
|
91
|
+
properties: {
|
|
92
|
+
hello: { type: 'string' }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
'text/plain': {
|
|
97
|
+
schema: { type: 'string' }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
104
|
+
t.type(opts[symbols.bodySchema]['application/json'], 'function')
|
|
105
|
+
t.type(opts[symbols.bodySchema]['text/plain'], 'function')
|
|
106
|
+
})
|
|
107
|
+
|
|
82
108
|
test('build schema - avoid repeated normalize schema', t => {
|
|
83
109
|
t.plan(3)
|
|
84
110
|
const serverConfig = {
|
|
@@ -94,10 +120,10 @@ test('build schema - avoid repeated normalize schema', t => {
|
|
|
94
120
|
}
|
|
95
121
|
}
|
|
96
122
|
}
|
|
97
|
-
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
123
|
+
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
|
|
98
124
|
t.not(kSchemaVisited, undefined)
|
|
99
125
|
t.equal(opts.schema[kSchemaVisited], true)
|
|
100
|
-
t.equal(opts.schema, normalizeSchema(opts.schema, serverConfig))
|
|
126
|
+
t.equal(opts.schema, normalizeSchema({}, opts.schema, serverConfig))
|
|
101
127
|
})
|
|
102
128
|
|
|
103
129
|
test('build schema - query schema', t => {
|
|
@@ -115,7 +141,7 @@ test('build schema - query schema', t => {
|
|
|
115
141
|
}
|
|
116
142
|
}
|
|
117
143
|
}
|
|
118
|
-
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
144
|
+
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
|
|
119
145
|
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
120
146
|
t.type(opts[symbols.querystringSchema].schema.type, 'string')
|
|
121
147
|
t.equal(typeof opts[symbols.querystringSchema], 'function')
|
|
@@ -133,7 +159,7 @@ test('build schema - query schema abbreviated', t => {
|
|
|
133
159
|
}
|
|
134
160
|
}
|
|
135
161
|
}
|
|
136
|
-
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
162
|
+
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
|
|
137
163
|
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
138
164
|
t.type(opts[symbols.querystringSchema].schema.type, 'string')
|
|
139
165
|
t.equal(typeof opts[symbols.querystringSchema], 'function')
|
|
@@ -168,7 +194,7 @@ test('build schema - querystring schema abbreviated', t => {
|
|
|
168
194
|
}
|
|
169
195
|
}
|
|
170
196
|
}
|
|
171
|
-
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
197
|
+
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
|
|
172
198
|
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
|
|
173
199
|
t.type(opts[symbols.querystringSchema].schema.type, 'string')
|
|
174
200
|
t.equal(typeof opts[symbols.querystringSchema], 'function')
|
|
@@ -196,7 +222,7 @@ test('build schema - must throw if querystring and query schema exist', t => {
|
|
|
196
222
|
}
|
|
197
223
|
}
|
|
198
224
|
}
|
|
199
|
-
opts.schema = normalizeSchema(opts.schema, serverConfig)
|
|
225
|
+
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
|
|
200
226
|
} catch (err) {
|
|
201
227
|
t.equal(err.code, 'FST_ERR_SCH_DUPLICATE')
|
|
202
228
|
t.equal(err.message, 'Schema with \'querystring\' already present!')
|
|
@@ -354,7 +380,7 @@ test('build schema - mixed schema types are individually skipped or normalized',
|
|
|
354
380
|
}]
|
|
355
381
|
|
|
356
382
|
testCases.forEach((testCase) => {
|
|
357
|
-
const result = normalizeSchema(testCase.schema, { jsonShorthand: true })
|
|
383
|
+
const result = normalizeSchema({}, testCase.schema, { jsonShorthand: true })
|
|
358
384
|
testCase.assertions(result)
|
|
359
385
|
})
|
|
360
386
|
})
|