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.
Files changed (398) hide show
  1. package/SPONSORS.md +2 -0
  2. package/docs/Guides/Migration-Guide-V4.md +52 -0
  3. package/docs/Reference/Routes.md +2 -1
  4. package/docs/Reference/Server.md +2 -0
  5. package/docs/Reference/Validation-and-Serialization.md +22 -0
  6. package/docs/Reference/Warnings.md +2 -0
  7. package/fastify.js +2 -2
  8. package/lib/handleRequest.js +2 -1
  9. package/lib/reply.js +21 -25
  10. package/lib/route.js +2 -2
  11. package/lib/schemas.js +22 -5
  12. package/lib/server.js +20 -9
  13. package/lib/validation.js +23 -2
  14. package/lib/warnings.js +6 -0
  15. package/package.json +1 -1
  16. package/test/close.test.js +4 -1
  17. package/test/copy.test.js +12 -5
  18. package/test/internals/validation.test.js +34 -8
  19. package/test/json-shorthand.test.js +131 -0
  20. package/test/listen.1.test.js +36 -0
  21. package/test/listen.5.test.js +99 -0
  22. package/test/mkcol.test.js +7 -4
  23. package/test/move.test.js +9 -6
  24. package/test/route.8.test.js +27 -0
  25. package/test/schema-feature.test.js +21 -0
  26. package/test/schema-validation.test.js +136 -0
  27. package/test/stream-serializers.test.js +37 -0
  28. package/test/throw.test.js +2 -2
  29. package/test/types/hooks.test-d.ts +4 -2
  30. package/test/types/route.test-d.ts +23 -0
  31. package/test/types/schema.test-d.ts +19 -0
  32. package/test/web-api.test.js +75 -0
  33. package/types/hooks.d.ts +2 -0
  34. package/types/route.d.ts +2 -2
  35. package/.tap/processinfo/029eb7a1-1942-40bc-98e2-cef3b7a14b5e.json +0 -268
  36. package/.tap/processinfo/03c196c6-01c3-4268-a9b5-298dff18a873.json +0 -269
  37. package/.tap/processinfo/04bbabba-8611-4908-9092-dfa9fcc13327.json +0 -268
  38. package/.tap/processinfo/05d8a743-3edf-4e2d-ae5a-dc99d0855ba5.json +0 -272
  39. package/.tap/processinfo/07718963-36a8-4d87-82ad-366c877a5247.json +0 -268
  40. package/.tap/processinfo/08fe3bde-5814-4308-9158-cdf1e47391b7.json +0 -268
  41. package/.tap/processinfo/0a3e3fb0-eabf-4532-ae80-20434da22678.json +0 -268
  42. package/.tap/processinfo/0caf2a75-4b3a-46c4-9b41-c7e450e5e15f.json +0 -268
  43. package/.tap/processinfo/0cf35d52-e5b2-4884-bcf0-b0ab3017b689.json +0 -268
  44. package/.tap/processinfo/0e666134-5013-4ecd-9ee6-59b22716c39c.json +0 -268
  45. package/.tap/processinfo/1087b811-4ec4-4f91-92b4-a78a51a437de.json +0 -268
  46. package/.tap/processinfo/13709ed3-b68c-42cf-8472-b0c4b8a89d2b.json +0 -268
  47. package/.tap/processinfo/13ac2f18-d0e0-439f-bc86-2ff0119af857.json +0 -268
  48. package/.tap/processinfo/13e47e0e-f6e8-4381-8a42-923b661f4a4f.json +0 -268
  49. package/.tap/processinfo/143f7d43-b8e8-4666-b482-f28fb37160ee.json +0 -268
  50. package/.tap/processinfo/14f3801d-03ab-4db3-9df5-c5d47e0a8cf0.json +0 -270
  51. package/.tap/processinfo/15a07dad-4bcd-442c-95e0-30c31f2b9818.json +0 -273
  52. package/.tap/processinfo/191ad3ad-04d8-4fb9-b119-ad2811f9b925.json +0 -243
  53. package/.tap/processinfo/1b25d54b-62d3-44cd-b581-31e705522fae.json +0 -268
  54. package/.tap/processinfo/1b7cb260-f04b-4135-a4fe-093081c4706f.json +0 -268
  55. package/.tap/processinfo/1e395d63-4815-4c77-aa47-df3709cc0ef9.json +0 -268
  56. package/.tap/processinfo/1e7f6a54-3abf-4771-863a-585cba110aec.json +0 -268
  57. package/.tap/processinfo/21a15e1d-0b41-47d8-b03d-0ba130969034.json +0 -244
  58. package/.tap/processinfo/21e02016-9ecd-4983-8417-9c74d224644f.json +0 -269
  59. package/.tap/processinfo/2327d941-d0d5-4762-b386-02a9a27ad28e.json +0 -268
  60. package/.tap/processinfo/23d39204-eac9-4f57-8db4-ffa996227fbd.json +0 -268
  61. package/.tap/processinfo/2493875a-0ac6-4d53-993c-f44471fd0678.json +0 -268
  62. package/.tap/processinfo/2698669f-f1e7-4a12-a687-8d58177be2b0.json +0 -269
  63. package/.tap/processinfo/2862b053-0a3d-46d7-9381-ffcb06287609.json +0 -268
  64. package/.tap/processinfo/2ac1b8d6-ac92-40e2-a59a-7681069f487c.json +0 -268
  65. package/.tap/processinfo/2c75e5f7-c4ef-47e4-a1c4-105eef6c0fab.json +0 -242
  66. package/.tap/processinfo/2e2c45cd-718b-4e5a-bf88-f801630f2803.json +0 -268
  67. package/.tap/processinfo/2f9ca478-3e03-4cce-a0bc-fcdc86d7c316.json +0 -268
  68. package/.tap/processinfo/30e3117f-fb74-456f-8f02-527e9eb9fcc3.json +0 -268
  69. package/.tap/processinfo/332be679-63c7-4b49-8b87-ef55995ada2d.json +0 -268
  70. package/.tap/processinfo/37c36f95-07f9-4ef0-8ab4-9e107d51b605.json +0 -269
  71. package/.tap/processinfo/3874eae2-f3db-44ef-9a9f-c8169d4b2b76.json +0 -268
  72. package/.tap/processinfo/38a7c3da-a411-41d0-8993-9deefd23500d.json +0 -268
  73. package/.tap/processinfo/3a7b6dbd-e153-4ce5-b557-21fb82009983.json +0 -269
  74. package/.tap/processinfo/3c6731ec-936d-470f-b7b0-0c87b54be051.json +0 -268
  75. package/.tap/processinfo/3c850ea9-4ef0-4044-a3fd-fbadfa9d543e.json +0 -268
  76. package/.tap/processinfo/3e4e15e0-a325-46f0-be57-5fd374560b7a.json +0 -269
  77. package/.tap/processinfo/3ed868e0-887c-402a-9f22-b1fdb74b4da0.json +0 -268
  78. package/.tap/processinfo/405498d7-5854-4ce1-a7dc-06920932f26d.json +0 -268
  79. package/.tap/processinfo/40b7eb19-ae35-4490-8a11-eb91a573c590.json +0 -268
  80. package/.tap/processinfo/40bb1260-d856-4248-8939-a0a05e322041.json +0 -268
  81. package/.tap/processinfo/41252e0b-7f69-44cc-b356-dd94bcbfdb29.json +0 -268
  82. package/.tap/processinfo/418fa710-e2fd-4508-b533-c179958da464.json +0 -269
  83. package/.tap/processinfo/433ef009-63aa-48fe-8e5d-c725228fa2fc.json +0 -268
  84. package/.tap/processinfo/44bf577c-9c01-4197-bd29-2e1ae888c4d4.json +0 -268
  85. package/.tap/processinfo/458fb7f2-20b9-48a2-8853-403c9851f605.json +0 -268
  86. package/.tap/processinfo/46b9892b-bb23-4b86-b0fa-9297f08c611a.json +0 -268
  87. package/.tap/processinfo/46bd9aaf-6cf3-4bd5-b90d-e136a7299a8e.json +0 -268
  88. package/.tap/processinfo/4779aa5f-e57a-4fcc-87e2-7d0bd4fca27f.json +0 -268
  89. package/.tap/processinfo/47b73f4b-ab31-49e1-97fd-8436dbe4bdf3.json +0 -269
  90. package/.tap/processinfo/49dba52e-e0c9-445d-8e9d-6d9ebe3ce6c4.json +0 -268
  91. package/.tap/processinfo/4b1dbc61-4e65-4c56-9784-2036f369038a.json +0 -268
  92. package/.tap/processinfo/4b6f0b40-43ef-4668-83a0-e07e28509df5.json +0 -268
  93. package/.tap/processinfo/4c236f70-f532-460b-8f7a-dd973301d493.json +0 -268
  94. package/.tap/processinfo/4d92b707-a268-48b8-885b-004d3a288c41.json +0 -269
  95. package/.tap/processinfo/4ff10bae-7c97-4c0a-b712-6c0d2f8c0e8e.json +0 -270
  96. package/.tap/processinfo/50f95bd5-ae12-4d83-99f4-ae9b0690c6a8.json +0 -268
  97. package/.tap/processinfo/557e4a49-d99c-4a63-b2f2-f33d897ab874.json +0 -268
  98. package/.tap/processinfo/589fd21a-8319-4abf-8cf7-82cb4a463a4b.json +0 -269
  99. package/.tap/processinfo/5a872f3a-949f-40be-8004-d739d034255c.json +0 -272
  100. package/.tap/processinfo/5abc301a-23da-424d-891e-3afbaff9156c.json +0 -269
  101. package/.tap/processinfo/5c31614c-a766-4837-ab59-dd6977166f72.json +0 -253
  102. package/.tap/processinfo/5d1e90c8-d819-4901-b022-f9ea4cd81978.json +0 -268
  103. package/.tap/processinfo/5d283e67-f31d-4fa8-a559-a1d8e82ee046.json +0 -269
  104. package/.tap/processinfo/5df505bc-6a4b-4c41-822f-51e2d7111de8.json +0 -268
  105. package/.tap/processinfo/5eaf64a2-fbfd-40e7-b391-c30f744b2bf1.json +0 -269
  106. package/.tap/processinfo/5ef5ede0-6436-4938-8401-d32ad4bffd5d.json +0 -268
  107. package/.tap/processinfo/606f05c0-8293-41db-bc92-eea82123697f.json +0 -269
  108. package/.tap/processinfo/6446806d-6cab-4c1d-a9ed-6bccaf3c4ea9.json +0 -268
  109. package/.tap/processinfo/64da7e08-925d-444d-98de-6568c6115d8d.json +0 -269
  110. package/.tap/processinfo/6917da6d-d2dc-466a-a893-7fb7412dde96.json +0 -268
  111. package/.tap/processinfo/69bbeee0-c398-4ccf-98b3-fb625a63bab4.json +0 -268
  112. package/.tap/processinfo/6da6ea8f-3370-4703-b230-90159531f766.json +0 -268
  113. package/.tap/processinfo/6ecffe1f-3016-4c11-9294-b488baced99f.json +0 -268
  114. package/.tap/processinfo/6f23f41f-ccbd-48cb-9ab6-311db0cfb65c.json +0 -270
  115. package/.tap/processinfo/70168912-9bb2-4334-bb89-041f1764cddf.json +0 -268
  116. package/.tap/processinfo/713a674e-40e1-46b4-866e-949d57c1a9f9.json +0 -270
  117. package/.tap/processinfo/730254d4-eacb-4cdf-80f4-8da22341cde5.json +0 -268
  118. package/.tap/processinfo/7344e559-c546-416f-8f1b-0f9fe12c6f02.json +0 -268
  119. package/.tap/processinfo/7556217a-0155-448f-b4d4-bec1bb0f6040.json +0 -269
  120. package/.tap/processinfo/7572079c-166c-4c4c-85ff-89b9430b214f.json +0 -268
  121. package/.tap/processinfo/7808180f-1974-47cd-bba2-2d6b8b711d65.json +0 -273
  122. package/.tap/processinfo/796dde83-da66-4db2-8d27-d45a3627c9c7.json +0 -268
  123. package/.tap/processinfo/7979819f-3723-48be-9f55-be700e689441.json +0 -270
  124. package/.tap/processinfo/7a664d39-d7f5-42f9-89df-15563048fab6.json +0 -268
  125. package/.tap/processinfo/7b047b72-01d9-4217-857c-93341651b4b3.json +0 -269
  126. package/.tap/processinfo/7ce41af6-7961-45ae-8c6f-b6e1c5692a48.json +0 -268
  127. package/.tap/processinfo/7e1de1c6-127e-463d-9357-081ee33ef5ce.json +0 -269
  128. package/.tap/processinfo/81ac7a7f-b0c0-4ef6-82cb-c718ea84e152.json +0 -268
  129. package/.tap/processinfo/851a058f-a497-4b10-a0b7-c9182d9c4d5a.json +0 -268
  130. package/.tap/processinfo/86502974-c245-4194-ade4-d9c6fdbb757e.json +0 -268
  131. package/.tap/processinfo/86b9786f-4a98-43b8-882a-5f936b876f08.json +0 -241
  132. package/.tap/processinfo/8a3fe726-86ab-4300-8d73-7eacbbc02a05.json +0 -268
  133. package/.tap/processinfo/8adf928b-c963-4ba0-9c35-606fcbd8a2aa.json +0 -272
  134. package/.tap/processinfo/8b31a6d8-1a33-4a27-93ca-1c5b364be068.json +0 -240
  135. package/.tap/processinfo/8ec12773-6b18-49a2-8e52-874c797df965.json +0 -833
  136. package/.tap/processinfo/8edb9502-3420-42fb-a602-e5de93be2df1.json +0 -268
  137. package/.tap/processinfo/8fc572e6-9828-4f98-a49c-9e081b2193c4.json +0 -242
  138. package/.tap/processinfo/8fee2d30-c5dd-4fae-9cf2-2ef8dd0f90de.json +0 -834
  139. package/.tap/processinfo/92cc0496-5f26-4370-8212-18136b972f99.json +0 -268
  140. package/.tap/processinfo/93a3f064-3f6e-4f49-becb-f7925f2961a9.json +0 -268
  141. package/.tap/processinfo/967e3697-8310-4a19-8dd5-927ac8bd6c79.json +0 -269
  142. package/.tap/processinfo/97225e23-9d30-4287-b3f5-72bccebec50b.json +0 -268
  143. package/.tap/processinfo/9a363bc6-4e65-47e8-94ca-26a9db428fb4.json +0 -268
  144. package/.tap/processinfo/9d2fe462-57fa-43f1-b02c-d188f15de30b.json +0 -270
  145. package/.tap/processinfo/a00b6cda-feb7-4b8a-8179-4c43bc29d670.json +0 -269
  146. package/.tap/processinfo/a017cbd5-4ac7-49e1-8c77-1bf4f6e7f2a6.json +0 -271
  147. package/.tap/processinfo/a1277309-1984-48f8-b60b-f5e8639736be.json +0 -271
  148. package/.tap/processinfo/a16bf53e-4337-48ff-88fa-67f55738e0f5.json +0 -268
  149. package/.tap/processinfo/a3a9848f-440e-41bb-9b0b-568bcfee0ddc.json +0 -268
  150. package/.tap/processinfo/a468c11f-f2f1-4e92-9ba0-6d28b6569b72.json +0 -268
  151. package/.tap/processinfo/a5880465-68f1-46b3-84a5-0da389d0bc67.json +0 -268
  152. package/.tap/processinfo/a666f394-39b4-44ad-8e74-abebf74dde3b.json +0 -270
  153. package/.tap/processinfo/af09d8ca-7053-4410-b514-b22c47f5979f.json +0 -268
  154. package/.tap/processinfo/af203309-28aa-459d-a56e-d88833695521.json +0 -268
  155. package/.tap/processinfo/afa2f7b6-dcd2-4d90-bf3c-54ba8b6800eb.json +0 -268
  156. package/.tap/processinfo/b231291d-ef14-4ff0-85f9-38a73a5408f8.json +0 -268
  157. package/.tap/processinfo/b3d3f2a1-a9fc-4d88-b122-fae90248cd59.json +0 -268
  158. package/.tap/processinfo/b834bf83-26c4-403a-8e91-eb15fe4b0b5d.json +0 -268
  159. package/.tap/processinfo/b8786fd7-47df-4ac1-8d6f-2d4c7623c681.json +0 -268
  160. package/.tap/processinfo/b9758f53-7f5a-4b03-8684-8a42ad644e5a.json +0 -268
  161. package/.tap/processinfo/bd194ea2-a21a-4604-b225-ee48abf1e607.json +0 -242
  162. package/.tap/processinfo/bd7ced53-3872-43b7-ad73-3352e50b728b.json +0 -268
  163. package/.tap/processinfo/be50295b-7e50-46cd-8bf1-637bf222699c.json +0 -268
  164. package/.tap/processinfo/bec61dd9-aa52-4e6c-8e37-5c9c10e935fd.json +0 -268
  165. package/.tap/processinfo/c015adf9-1d60-447e-87b5-b2031fe55bba.json +0 -268
  166. package/.tap/processinfo/c0666afa-7f64-45bd-97fb-145df1380157.json +0 -268
  167. package/.tap/processinfo/c2c0c012-c1c0-4457-84d6-dadba8396c94.json +0 -268
  168. package/.tap/processinfo/c3dd3ecd-737b-47ce-a917-54341c7bbed3.json +0 -268
  169. package/.tap/processinfo/c41ac06d-64b8-4bb3-bf56-0551f5a48f4b.json +0 -268
  170. package/.tap/processinfo/c4235bfb-a2aa-4271-9c6b-3ceb370219b1.json +0 -268
  171. package/.tap/processinfo/c4e6f24f-288c-493c-b6f0-02924aeb6758.json +0 -270
  172. package/.tap/processinfo/c54227bb-4a7b-40bb-bfe6-b54fe55078f3.json +0 -268
  173. package/.tap/processinfo/c699de91-3b0b-4466-9418-6910a3eb640a.json +0 -269
  174. package/.tap/processinfo/c74e2f37-451a-4577-ac18-e597fbd9a1d4.json +0 -269
  175. package/.tap/processinfo/c90cccec-5b4b-445f-a935-ac22859675d0.json +0 -252
  176. package/.tap/processinfo/c9dd6c7d-0d16-45e5-87ae-117388bf2994.json +0 -268
  177. package/.tap/processinfo/ca2e48fb-58c5-47fc-ad2e-263838aea42c.json +0 -272
  178. package/.tap/processinfo/ca87351d-c710-45c1-838a-16bccac59874.json +0 -273
  179. package/.tap/processinfo/cdb4a671-5776-4944-91b9-c456c58841ef.json +0 -268
  180. package/.tap/processinfo/cf10fdc8-6a87-447a-9e12-45f447af61f3.json +0 -244
  181. package/.tap/processinfo/cf3f1f08-643e-4f24-82ca-40f7a349c3d1.json +0 -268
  182. package/.tap/processinfo/d091172a-06a5-469b-82a9-8fefe3dd99da.json +0 -240
  183. package/.tap/processinfo/d1675431-61d6-45f8-a010-6e654112a00a.json +0 -272
  184. package/.tap/processinfo/d2d54aa2-c221-4ad4-b6b7-0c58e3c3679c.json +0 -269
  185. package/.tap/processinfo/d4f3c95a-ddbe-419d-bce0-dd6acceee21f.json +0 -268
  186. package/.tap/processinfo/d54ed8f1-43c3-478a-90d3-2c8aced723f2.json +0 -269
  187. package/.tap/processinfo/d6e5a2a6-4647-4d98-916c-aec4ace54a65.json +0 -268
  188. package/.tap/processinfo/d7280c64-45e6-4b12-affc-3ac9a5d4014a.json +0 -268
  189. package/.tap/processinfo/d82c8367-d825-4405-88df-07298f6ef840.json +0 -269
  190. package/.tap/processinfo/d8f97e53-e921-4d33-9c8d-2f7e807a9425.json +0 -268
  191. package/.tap/processinfo/da546a73-9714-4f8c-bdbb-e42730edbcfa.json +0 -268
  192. package/.tap/processinfo/da7fb7fb-1da4-49f8-a3ee-d4ea623c01a5.json +0 -268
  193. package/.tap/processinfo/daa6a016-4f0c-4050-923c-2022e0bb21d8.json +0 -268
  194. package/.tap/processinfo/db9a251d-8540-4719-b464-e7d5febd97d1.json +0 -240
  195. package/.tap/processinfo/dc10c603-8e58-4611-baa3-44da2578d07a.json +0 -268
  196. package/.tap/processinfo/dde56c1a-858c-47cc-b0bb-61279620ac17.json +0 -268
  197. package/.tap/processinfo/e0d9c4ea-f7c7-4c64-8ced-66dc6f0ac5d2.json +0 -271
  198. package/.tap/processinfo/e121454f-5dfa-4209-ba15-4c39840871f2.json +0 -831
  199. package/.tap/processinfo/e1f43e40-c3fe-4eb8-a713-d5910cc6b25a.json +0 -268
  200. package/.tap/processinfo/e4575e7a-f00e-488b-94e1-8f877b54725e.json +0 -268
  201. package/.tap/processinfo/e9ad667e-8603-4488-af64-449cc9532803.json +0 -268
  202. package/.tap/processinfo/eb26a697-e5e2-4730-aeea-bcb9c49afd4d.json +0 -268
  203. package/.tap/processinfo/eb29d1c3-feaf-4744-9d84-cf257e8269b0.json +0 -268
  204. package/.tap/processinfo/ee720c0a-ed64-4e7e-8c0a-139c7b9725d2.json +0 -268
  205. package/.tap/processinfo/ef88c13a-87b2-49e4-a683-7b812505cd6f.json +0 -268
  206. package/.tap/processinfo/f4ed6948-dac0-4128-9f86-d083b6918ea7.json +0 -268
  207. package/.tap/processinfo/f7544c01-8ac7-4e42-8ad5-c4d62e094d1f.json +0 -270
  208. package/.tap/processinfo/f7cee4b3-7bcc-4591-a628-5629b0b41c9e.json +0 -268
  209. package/.tap/processinfo/f9c0a1f7-c1a4-44d3-ae3f-8c1eb42cd746.json +0 -269
  210. package/.tap/processinfo/fc46b4da-79db-4201-af7e-34bb17f92d69.json +0 -270
  211. package/.tap/processinfo/fccc0056-03c4-40cb-9d0b-2db4bbe573c1.json +0 -268
  212. package/.tap/processinfo/fd2df572-54d7-4ce7-b7aa-a2b4b00d4127.json +0 -254
  213. package/.tap/processinfo/fea9377f-b473-484d-bee6-ac7f49e50937.json +0 -269
  214. package/.tap/processinfo/feb516dc-abda-46e6-9b42-d37adfc63366.json +0 -268
  215. package/.tap/processinfo/ff0fda4c-aa2e-4236-906e-fdfb6bd6632e.json +0 -269
  216. package/.tap/test-results/test/404s.test.js.tap +0 -623
  217. package/.tap/test-results/test/500s.test.js.tap +0 -64
  218. package/.tap/test-results/test/allowUnsafeRegex.test.js.tap +0 -36
  219. package/.tap/test-results/test/als.test.js.tap +0 -15
  220. package/.tap/test-results/test/async-await.test.js.tap +0 -184
  221. package/.tap/test-results/test/async-dispose.test.js.tap +0 -8
  222. package/.tap/test-results/test/async_hooks.test.js.tap +0 -10
  223. package/.tap/test-results/test/bodyLimit.test.js.tap +0 -48
  224. package/.tap/test-results/test/buffer.test.js.tap +0 -20
  225. package/.tap/test-results/test/build/error-serializer.test.js.tap +0 -8
  226. package/.tap/test-results/test/build/version.test.js.tap +0 -7
  227. package/.tap/test-results/test/case-insensitive.test.js.tap +0 -36
  228. package/.tap/test-results/test/chainable.test.js.tap +0 -17
  229. package/.tap/test-results/test/check.test.js.tap +0 -10
  230. package/.tap/test-results/test/childLoggerFactory.test.js.tap +0 -23
  231. package/.tap/test-results/test/client-timeout.test.js.tap +0 -7
  232. package/.tap/test-results/test/close-pipelining.test.js.tap +0 -15
  233. package/.tap/test-results/test/close.test.js.tap +0 -172
  234. package/.tap/test-results/test/connectionTimeout.test.js.tap +0 -12
  235. package/.tap/test-results/test/constrained-routes.test.js.tap +0 -173
  236. package/.tap/test-results/test/content-length.test.js.tap +0 -46
  237. package/.tap/test-results/test/content-parser.test.js.tap +0 -266
  238. package/.tap/test-results/test/content-type.test.js.tap +0 -14
  239. package/.tap/test-results/test/context-config.test.js.tap +0 -41
  240. package/.tap/test-results/test/copy.test.js.tap +0 -14
  241. package/.tap/test-results/test/custom-http-server.test.js.tap +0 -30
  242. package/.tap/test-results/test/custom-parser-async.test.js.tap +0 -21
  243. package/.tap/test-results/test/custom-parser.0.test.js.tap +0 -199
  244. package/.tap/test-results/test/custom-parser.1.test.js.tap +0 -90
  245. package/.tap/test-results/test/custom-parser.2.test.js.tap +0 -22
  246. package/.tap/test-results/test/custom-parser.3.test.js.tap +0 -53
  247. package/.tap/test-results/test/custom-parser.4.test.js.tap +0 -45
  248. package/.tap/test-results/test/custom-parser.5.test.js.tap +0 -41
  249. package/.tap/test-results/test/custom-querystring-parser.test.js.tap +0 -46
  250. package/.tap/test-results/test/decorator.test.js.tap +0 -465
  251. package/.tap/test-results/test/delete.test.js.tap +0 -110
  252. package/.tap/test-results/test/diagnostics-channel/404.test.js.tap +0 -15
  253. package/.tap/test-results/test/diagnostics-channel/async-delay-request.test.js.tap +0 -25
  254. package/.tap/test-results/test/diagnostics-channel/async-request.test.js.tap +0 -24
  255. package/.tap/test-results/test/diagnostics-channel/error-before-handler.test.js.tap +0 -9
  256. package/.tap/test-results/test/diagnostics-channel/error-request.test.js.tap +0 -20
  257. package/.tap/test-results/test/diagnostics-channel/error-status.test.js.tap +0 -10
  258. package/.tap/test-results/test/diagnostics-channel/init.test.js.tap +0 -14
  259. package/.tap/test-results/test/diagnostics-channel/sync-delay-request.test.js.tap +0 -16
  260. package/.tap/test-results/test/diagnostics-channel/sync-request-reply.test.js.tap +0 -16
  261. package/.tap/test-results/test/diagnostics-channel/sync-request.test.js.tap +0 -19
  262. package/.tap/test-results/test/encapsulated-child-logger-factory.test.js.tap +0 -18
  263. package/.tap/test-results/test/encapsulated-error-handler.test.js.tap +0 -243
  264. package/.tap/test-results/test/esm/errorCodes.test.mjs.tap +0 -9
  265. package/.tap/test-results/test/esm/esm.test.mjs.tap +0 -8
  266. package/.tap/test-results/test/esm/index.test.js.tap +0 -8
  267. package/.tap/test-results/test/fastify-instance.test.js.tap +0 -114
  268. package/.tap/test-results/test/findRoute.test.js.tap +0 -37
  269. package/.tap/test-results/test/fluent-schema.test.js.tap +0 -36
  270. package/.tap/test-results/test/genReqId.test.js.tap +0 -106
  271. package/.tap/test-results/test/get.test.js.tap +0 -151
  272. package/.tap/test-results/test/handler-context.test.js.tap +0 -19
  273. package/.tap/test-results/test/has-route.test.js.tap +0 -30
  274. package/.tap/test-results/test/head.test.js.tap +0 -130
  275. package/.tap/test-results/test/header-overflow.test.js.tap +0 -16
  276. package/.tap/test-results/test/hooks-async.test.js.tap +0 -286
  277. package/.tap/test-results/test/hooks.on-listen.test.js.tap +0 -311
  278. package/.tap/test-results/test/hooks.on-ready.test.js.tap +0 -151
  279. package/.tap/test-results/test/hooks.test.js.tap +0 -966
  280. package/.tap/test-results/test/http2/closing.test.js.tap +0 -35
  281. package/.tap/test-results/test/http2/constraint.test.js.tap +0 -32
  282. package/.tap/test-results/test/http2/head.test.js.tap +0 -9
  283. package/.tap/test-results/test/http2/missing-http2-module.test.js.tap +0 -8
  284. package/.tap/test-results/test/http2/plain.test.js.tap +0 -22
  285. package/.tap/test-results/test/http2/secure-with-fallback.test.js.tap +0 -40
  286. package/.tap/test-results/test/http2/secure.test.js.tap +0 -27
  287. package/.tap/test-results/test/http2/unknown-http-method.test.js.tap +0 -9
  288. package/.tap/test-results/test/https/custom-https-server.test.js.tap +0 -10
  289. package/.tap/test-results/test/https/https.test.js.tap +0 -45
  290. package/.tap/test-results/test/imports.test.js.tap +0 -14
  291. package/.tap/test-results/test/inject.test.js.tap +0 -165
  292. package/.tap/test-results/test/internals/all.test.js.tap +0 -42
  293. package/.tap/test-results/test/internals/contentTypeParser.test.js.tap +0 -14
  294. package/.tap/test-results/test/internals/context.test.js.tap +0 -14
  295. package/.tap/test-results/test/internals/decorator.test.js.tap +0 -51
  296. package/.tap/test-results/test/internals/errors.test.js.tap +0 -1212
  297. package/.tap/test-results/test/internals/handleRequest.test.js.tap +0 -69
  298. package/.tap/test-results/test/internals/hookRunner.test.js.tap +0 -143
  299. package/.tap/test-results/test/internals/hooks.test.js.tap +0 -45
  300. package/.tap/test-results/test/internals/initialConfig.test.js.tap +0 -125
  301. package/.tap/test-results/test/internals/logger.test.js.tap +0 -71
  302. package/.tap/test-results/test/internals/plugin.test.js.tap +0 -48
  303. package/.tap/test-results/test/internals/reply-serialize.test.js.tap +0 -166
  304. package/.tap/test-results/test/internals/reply.test.js.tap +0 -688
  305. package/.tap/test-results/test/internals/reqIdGenFactory.test.js.tap +0 -74
  306. package/.tap/test-results/test/internals/request-validate.test.js.tap +0 -384
  307. package/.tap/test-results/test/internals/request.test.js.tap +0 -163
  308. package/.tap/test-results/test/internals/server.test.js.tap +0 -30
  309. package/.tap/test-results/test/internals/validation.test.js.tap +0 -121
  310. package/.tap/test-results/test/keepAliveTimeout.test.js.tap +0 -12
  311. package/.tap/test-results/test/listen.1.test.js.tap +0 -31
  312. package/.tap/test-results/test/listen.2.test.js.tap +0 -46
  313. package/.tap/test-results/test/listen.3.test.js.tap +0 -25
  314. package/.tap/test-results/test/listen.4.test.js.tap +0 -51
  315. package/.tap/test-results/test/lock.test.js.tap +0 -29
  316. package/.tap/test-results/test/logger/instantiation.test.js.tap +0 -92
  317. package/.tap/test-results/test/logger/logging.test.js.tap +0 -117
  318. package/.tap/test-results/test/logger/options.test.js.tap +0 -165
  319. package/.tap/test-results/test/logger/request.test.js.tap +0 -82
  320. package/.tap/test-results/test/logger/response.test.js.tap +0 -38
  321. package/.tap/test-results/test/maxRequestsPerSocket.test.js.tap +0 -44
  322. package/.tap/test-results/test/method-missing.test.js.tap +0 -8
  323. package/.tap/test-results/test/middleware.test.js.tap +0 -17
  324. package/.tap/test-results/test/mkcalendar.test.js.tap +0 -43
  325. package/.tap/test-results/test/mkcol.test.js.tap +0 -14
  326. package/.tap/test-results/test/move.test.js.tap +0 -15
  327. package/.tap/test-results/test/noop-set.test.js.tap +0 -8
  328. package/.tap/test-results/test/nullable-validation.test.js.tap +0 -36
  329. package/.tap/test-results/test/options.error-handler.test.js.tap +0 -186
  330. package/.tap/test-results/test/options.test.js.tap +0 -174
  331. package/.tap/test-results/test/output-validation.test.js.tap +0 -66
  332. package/.tap/test-results/test/patch.error-handler.test.js.tap +0 -206
  333. package/.tap/test-results/test/patch.test.js.tap +0 -182
  334. package/.tap/test-results/test/plugin.1.test.js.tap +0 -78
  335. package/.tap/test-results/test/plugin.2.test.js.tap +0 -102
  336. package/.tap/test-results/test/plugin.3.test.js.tap +0 -58
  337. package/.tap/test-results/test/plugin.4.test.js.tap +0 -164
  338. package/.tap/test-results/test/post-empty-body.test.js.tap +0 -8
  339. package/.tap/test-results/test/pretty-print.test.js.tap +0 -82
  340. package/.tap/test-results/test/promises.test.js.tap +0 -46
  341. package/.tap/test-results/test/propfind.test.js.tap +0 -43
  342. package/.tap/test-results/test/proppatch.test.js.tap +0 -29
  343. package/.tap/test-results/test/proto-poisoning.test.js.tap +0 -47
  344. package/.tap/test-results/test/put.error-handler.test.js.tap +0 -206
  345. package/.tap/test-results/test/put.test.js.tap +0 -182
  346. package/.tap/test-results/test/register.test.js.tap +0 -61
  347. package/.tap/test-results/test/reply-code.test.js.tap +0 -40
  348. package/.tap/test-results/test/reply-earlyHints.test.js.tap +0 -22
  349. package/.tap/test-results/test/reply-error.test.js.tap +0 -643
  350. package/.tap/test-results/test/reply-trailers.test.js.tap +0 -176
  351. package/.tap/test-results/test/report.test.js.tap +0 -43
  352. package/.tap/test-results/test/request-error.test.js.tap +0 -98
  353. package/.tap/test-results/test/request-id.test.js.tap +0 -38
  354. package/.tap/test-results/test/request.deprecated.test.js.tap +0 -13
  355. package/.tap/test-results/test/requestTimeout.test.js.tap +0 -21
  356. package/.tap/test-results/test/route-hooks.test.js.tap +0 -498
  357. package/.tap/test-results/test/route-prefix.test.js.tap +0 -195
  358. package/.tap/test-results/test/route-shorthand.test.js.tap +0 -190
  359. package/.tap/test-results/test/route.1.test.js.tap +0 -93
  360. package/.tap/test-results/test/route.2.test.js.tap +0 -28
  361. package/.tap/test-results/test/route.3.test.js.tap +0 -39
  362. package/.tap/test-results/test/route.4.test.js.tap +0 -32
  363. package/.tap/test-results/test/route.5.test.js.tap +0 -54
  364. package/.tap/test-results/test/route.6.test.js.tap +0 -81
  365. package/.tap/test-results/test/route.7.test.js.tap +0 -93
  366. package/.tap/test-results/test/route.8.test.js.tap +0 -38
  367. package/.tap/test-results/test/router-options.test.js.tap +0 -104
  368. package/.tap/test-results/test/same-shape.test.js.tap +0 -22
  369. package/.tap/test-results/test/schema-examples.test.js.tap +0 -85
  370. package/.tap/test-results/test/schema-feature.test.js.tap +0 -445
  371. package/.tap/test-results/test/schema-serialization.test.js.tap +0 -194
  372. package/.tap/test-results/test/schema-special-usage.test.js.tap +0 -186
  373. package/.tap/test-results/test/schema-validation.test.js.tap +0 -199
  374. package/.tap/test-results/test/search.test.js.tap +0 -77
  375. package/.tap/test-results/test/serialize-response.test.js.tap +0 -26
  376. package/.tap/test-results/test/server.test.js.tap +0 -65
  377. package/.tap/test-results/test/set-error-handler.test.js.tap +0 -7
  378. package/.tap/test-results/test/skip-reply-send.test.js.tap +0 -272
  379. package/.tap/test-results/test/stream.1.test.js.tap +0 -36
  380. package/.tap/test-results/test/stream.2.test.js.tap +0 -20
  381. package/.tap/test-results/test/stream.3.test.js.tap +0 -34
  382. package/.tap/test-results/test/stream.4.test.js.tap +0 -40
  383. package/.tap/test-results/test/stream.5.test.js.tap +0 -37
  384. package/.tap/test-results/test/sync-routes.test.js.tap +0 -19
  385. package/.tap/test-results/test/throw.test.js.tap +0 -116
  386. package/.tap/test-results/test/trace.test.js.tap +0 -7
  387. package/.tap/test-results/test/trust-proxy.test.js.tap +0 -109
  388. package/.tap/test-results/test/type-provider.test.js.tap +0 -12
  389. package/.tap/test-results/test/unlock.test.js.tap +0 -14
  390. package/.tap/test-results/test/upgrade.test.js.tap +0 -8
  391. package/.tap/test-results/test/url-rewriting.test.js.tap +0 -39
  392. package/.tap/test-results/test/useSemicolonDelimiter.test.js.tap +0 -33
  393. package/.tap/test-results/test/validation-error-handling.test.js.tap +0 -180
  394. package/.tap/test-results/test/versioned-routes.test.js.tap +0 -151
  395. package/.tap/test-results/test/web-api.test.js.tap +0 -51
  396. package/.tap/test-results/test/wrapThenable.test.js.tap +0 -11
  397. package/EXPENSE_POLICY.md +0 -105
  398. package/test/types/import.js +0 -2
@@ -0,0 +1,131 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('tap')
4
+ const Fastify = require('..')
5
+ const {
6
+ FSTDEP022
7
+ } = require('../lib/warnings')
8
+
9
+ test('use of deprecated json shorthand in params should warn', t => {
10
+ t.plan(3)
11
+
12
+ process.removeAllListeners('warning')
13
+ process.on('warning', onWarning)
14
+ function onWarning (warning) {
15
+ t.equal(warning.name, 'DeprecationWarning')
16
+ t.equal(warning.code, FSTDEP022.code)
17
+ }
18
+
19
+ const fastify = Fastify()
20
+
21
+ fastify.get('/:id', {
22
+ schema: {
23
+ params: {
24
+ id: { type: 'string' }
25
+ }
26
+ }
27
+ }, (_, reply) => {
28
+ return reply.code(200).send('')
29
+ })
30
+
31
+ fastify.inject({ method: 'GET', url: '/1' }, (err, res) => {
32
+ t.error(err)
33
+
34
+ process.removeListener('warning', onWarning)
35
+ })
36
+
37
+ FSTDEP022.emitted = false
38
+ })
39
+
40
+ test('use of deprecated json shorthand in headers should warn', t => {
41
+ t.plan(3)
42
+
43
+ process.removeAllListeners('warning')
44
+ process.on('warning', onWarning)
45
+ function onWarning (warning) {
46
+ t.equal(warning.name, 'DeprecationWarning')
47
+ t.equal(warning.code, FSTDEP022.code)
48
+ }
49
+
50
+ const fastify = Fastify()
51
+
52
+ fastify.get('/', {
53
+ schema: {
54
+ headers: {
55
+ hello: { type: 'string' }
56
+ }
57
+ }
58
+ }, (_, reply) => {
59
+ return reply.code(200).send('')
60
+ })
61
+
62
+ fastify.inject({ method: 'GET', url: '/' }, (err, res) => {
63
+ t.error(err)
64
+
65
+ process.removeListener('warning', onWarning)
66
+ })
67
+
68
+ FSTDEP022.emitted = false
69
+ })
70
+
71
+ test('use of deprecated json shorthand in querystring should warn', t => {
72
+ t.plan(3)
73
+
74
+ process.removeAllListeners('warning')
75
+ process.on('warning', onWarning)
76
+ function onWarning (warning) {
77
+ t.equal(warning.name, 'DeprecationWarning')
78
+ t.equal(warning.code, FSTDEP022.code)
79
+ }
80
+
81
+ const fastify = Fastify()
82
+
83
+ fastify.get('/', {
84
+ schema: {
85
+ querystring: {
86
+ hello: { type: 'string' }
87
+ }
88
+ }
89
+ }, (_, reply) => {
90
+ return reply.code(200).send('')
91
+ })
92
+
93
+ fastify.inject({ method: 'GET', url: '/', query: { hello: 'world' } }, (err, res) => {
94
+ t.error(err)
95
+
96
+ process.removeListener('warning', onWarning)
97
+ })
98
+
99
+ FSTDEP022.emitted = false
100
+ })
101
+
102
+ test('use of deprecated json shorthand in body should warn', t => {
103
+ t.plan(3)
104
+
105
+ process.removeAllListeners('warning')
106
+ process.on('warning', onWarning)
107
+ function onWarning (warning) {
108
+ t.equal(warning.name, 'DeprecationWarning')
109
+ t.equal(warning.code, FSTDEP022.code)
110
+ }
111
+
112
+ const fastify = Fastify()
113
+
114
+ fastify.post('/', {
115
+ schema: {
116
+ body: {
117
+ hello: { type: 'string' }
118
+ }
119
+ }
120
+ }, (_, reply) => {
121
+ return reply.code(200).send('')
122
+ })
123
+
124
+ fastify.inject({ method: 'POST', url: '/', body: { hello: 'world' } }, (err, res) => {
125
+ t.error(err)
126
+
127
+ process.removeListener('warning', onWarning)
128
+ })
129
+
130
+ FSTDEP022.emitted = false
131
+ })
@@ -99,3 +99,39 @@ test('listen after Promise.resolve()', t => {
99
99
  })
100
100
  })
101
101
  })
102
+
103
+ test('listen works with undefined host', async t => {
104
+ const doNotWarn = () => {
105
+ t.fail('should not be deprecated')
106
+ }
107
+ process.on('warning', doNotWarn)
108
+
109
+ const fastify = Fastify()
110
+ t.teardown(fastify.close.bind(fastify))
111
+ t.teardown(() => {
112
+ fastify.close()
113
+ process.removeListener('warning', doNotWarn)
114
+ })
115
+ await fastify.listen({ host: undefined, port: 0 })
116
+ const address = fastify.server.address()
117
+ t.equal(address.address, localhost)
118
+ t.ok(address.port > 0)
119
+ })
120
+
121
+ test('listen works with null host', async t => {
122
+ const doNotWarn = () => {
123
+ t.fail('should not be deprecated')
124
+ }
125
+ process.on('warning', doNotWarn)
126
+
127
+ const fastify = Fastify()
128
+ t.teardown(fastify.close.bind(fastify))
129
+ t.teardown(() => {
130
+ fastify.close()
131
+ process.removeListener('warning', doNotWarn)
132
+ })
133
+ await fastify.listen({ host: null, port: 0 })
134
+ const address = fastify.server.address()
135
+ t.equal(address.address, localhost)
136
+ t.ok(address.port > 0)
137
+ })
@@ -0,0 +1,99 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('tap')
4
+ const net = require('node:net')
5
+ const Fastify = require('../fastify')
6
+ const { once } = require('node:events')
7
+
8
+ function createDeferredPromise () {
9
+ const promise = {}
10
+ promise.promise = new Promise((resolve) => {
11
+ promise.resolve = resolve
12
+ })
13
+ return promise
14
+ }
15
+
16
+ test('same port conflict and success should not fire callback multiple times - callback', async (t) => {
17
+ t.plan(7)
18
+ const server = net.createServer()
19
+ server.listen({ port: 0, host: '127.0.0.1' })
20
+ await once(server, 'listening')
21
+ const option = { port: server.address().port, host: server.address().address }
22
+ let count = 0
23
+ const fastify = Fastify()
24
+ const promise = createDeferredPromise()
25
+ function callback (err) {
26
+ switch (count) {
27
+ case 6: {
28
+ // success in here
29
+ t.error(err)
30
+ fastify.close((err) => {
31
+ t.error(err)
32
+ promise.resolve()
33
+ })
34
+ break
35
+ }
36
+ case 5: {
37
+ server.close()
38
+ setTimeout(() => {
39
+ fastify.listen(option, callback)
40
+ }, 100)
41
+ break
42
+ }
43
+ default: {
44
+ // expect error
45
+ t.equal(err.code, 'EADDRINUSE')
46
+ setTimeout(() => {
47
+ fastify.listen(option, callback)
48
+ }, 100)
49
+ }
50
+ }
51
+ count++
52
+ }
53
+ fastify.listen(option, callback)
54
+ await promise.promise
55
+ })
56
+
57
+ test('same port conflict and success should not fire callback multiple times - promise', async (t) => {
58
+ t.plan(5)
59
+ const server = net.createServer()
60
+ server.listen({ port: 0, host: '127.0.0.1' })
61
+ await once(server, 'listening')
62
+ const option = { port: server.address().port, host: server.address().address }
63
+ const fastify = Fastify()
64
+
65
+ try {
66
+ await fastify.listen(option)
67
+ } catch (err) {
68
+ t.equal(err.code, 'EADDRINUSE')
69
+ }
70
+ try {
71
+ await fastify.listen(option)
72
+ } catch (err) {
73
+ t.equal(err.code, 'EADDRINUSE')
74
+ }
75
+ try {
76
+ await fastify.listen(option)
77
+ } catch (err) {
78
+ t.equal(err.code, 'EADDRINUSE')
79
+ }
80
+ try {
81
+ await fastify.listen(option)
82
+ } catch (err) {
83
+ t.equal(err.code, 'EADDRINUSE')
84
+ }
85
+ try {
86
+ await fastify.listen(option)
87
+ } catch (err) {
88
+ t.equal(err.code, 'EADDRINUSE')
89
+ }
90
+
91
+ server.close()
92
+
93
+ await once(server, 'close')
94
+
95
+ // when ever we can listen, and close properly
96
+ // which means there is no problem on the callback
97
+ await fastify.listen()
98
+ await fastify.close()
99
+ })
@@ -12,7 +12,7 @@ test('can be created - mkcol', t => {
12
12
  method: 'MKCOL',
13
13
  url: '*',
14
14
  handler: function (req, reply) {
15
- reply.code(201).send()
15
+ reply.code(201).header('body', req.body.toString()).send()
16
16
  }
17
17
  })
18
18
  t.pass()
@@ -26,12 +26,15 @@ fastify.listen({ port: 0 }, err => {
26
26
  t.teardown(() => { fastify.close() })
27
27
 
28
28
  test('request - mkcol', t => {
29
- t.plan(2)
29
+ t.plan(3)
30
30
  sget({
31
31
  url: `http://localhost:${fastify.server.address().port}/test/`,
32
- method: 'MKCOL'
33
- }, (err, response, body) => {
32
+ method: 'MKCOL',
33
+ headers: { 'Content-Type': 'text/plain' },
34
+ body: '/test.txt'
35
+ }, (err, response) => {
34
36
  t.error(err)
37
+ t.equal(response.headers.body, '/test.txt')
35
38
  t.equal(response.statusCode, 201)
36
39
  })
37
40
  })
package/test/move.test.js CHANGED
@@ -12,9 +12,9 @@ test('shorthand - move', t => {
12
12
  method: 'MOVE',
13
13
  url: '*',
14
14
  handler: function (req, reply) {
15
- const destination = req.headers.destination
16
15
  reply.code(201)
17
- .header('location', destination)
16
+ .header('location', req.headers.destination)
17
+ .header('body', req.body.toString())
18
18
  .send()
19
19
  }
20
20
  })
@@ -29,17 +29,20 @@ fastify.listen({ port: 0 }, err => {
29
29
  t.teardown(() => { fastify.close() })
30
30
 
31
31
  test('request - move', t => {
32
- t.plan(3)
32
+ t.plan(4)
33
33
  sget({
34
34
  url: `http://localhost:${fastify.server.address().port}/test.txt`,
35
35
  method: 'MOVE',
36
36
  headers: {
37
- Destination: '/test2.txt'
38
- }
39
- }, (err, response, body) => {
37
+ destination: '/test2.txt',
38
+ 'Content-Type': 'text/plain'
39
+ },
40
+ body: '/test3.txt'
41
+ }, (err, response) => {
40
42
  t.error(err)
41
43
  t.equal(response.statusCode, 201)
42
44
  t.equal(response.headers.location, '/test2.txt')
45
+ t.equal(response.headers.body, '/test3.txt')
43
46
  })
44
47
  })
45
48
  })
@@ -140,3 +140,30 @@ test('using fastify.all when a catchall is defined does not degrade performance'
140
140
 
141
141
  t.pass()
142
142
  })
143
+
144
+ test('Adding manually HEAD route after GET with the same path throws Fastify duplicated route instance error', t => {
145
+ t.plan(1)
146
+
147
+ const fastify = Fastify()
148
+
149
+ fastify.route({
150
+ method: 'GET',
151
+ path: '/:param1',
152
+ handler: (req, reply) => {
153
+ reply.send({ hello: 'world' })
154
+ }
155
+ })
156
+
157
+ try {
158
+ fastify.route({
159
+ method: 'HEAD',
160
+ path: '/:param2',
161
+ handler: (req, reply) => {
162
+ reply.send({ hello: 'world' })
163
+ }
164
+ })
165
+ t.fail('Should throw fastify duplicated route declaration')
166
+ } catch (error) {
167
+ t.equal(error.code, 'FST_ERR_DUPLICATED_ROUTE')
168
+ }
169
+ })
@@ -190,6 +190,27 @@ test('Should throw of the schema does not exists in input', t => {
190
190
  })
191
191
  })
192
192
 
193
+ test('Should throw if schema is missing for content type', t => {
194
+ t.plan(2)
195
+
196
+ const fastify = Fastify()
197
+ fastify.post('/', {
198
+ handler: echoBody,
199
+ schema: {
200
+ body: {
201
+ content: {
202
+ 'application/json': {}
203
+ }
204
+ }
205
+ }
206
+ })
207
+
208
+ fastify.ready(err => {
209
+ t.equal(err.code, 'FST_ERR_SCH_CONTENT_MISSING_SCHEMA')
210
+ t.equal(err.message, "Schema is missing for the content type 'application/json'")
211
+ })
212
+ })
213
+
193
214
  test('Should throw of the schema does not exists in output', t => {
194
215
  t.plan(2)
195
216
  const fastify = Fastify()
@@ -105,6 +105,142 @@ test('Basic validation test', t => {
105
105
  })
106
106
  })
107
107
 
108
+ test('Different schema per content type', t => {
109
+ t.plan(12)
110
+
111
+ const fastify = Fastify()
112
+ fastify.addContentTypeParser('application/octet-stream', {
113
+ parseAs: 'buffer'
114
+ }, async function (_, payload) {
115
+ return payload
116
+ })
117
+ fastify.post('/', {
118
+ schema: {
119
+ body: {
120
+ content: {
121
+ 'application/json': {
122
+ schema: schemaArtist
123
+ },
124
+ 'application/octet-stream': {
125
+ schema: {} // Skip validation
126
+ },
127
+ 'text/plain': {
128
+ schema: { type: 'string' }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }, async function (req, reply) {
134
+ return reply.send(req.body)
135
+ })
136
+
137
+ fastify.inject({
138
+ url: '/',
139
+ method: 'POST',
140
+ headers: { 'Content-Type': 'application/json' },
141
+ body: {
142
+ name: 'michelangelo',
143
+ work: 'sculptor, painter, architect and poet'
144
+ }
145
+ }, (err, res) => {
146
+ t.error(err)
147
+ t.same(JSON.parse(res.payload).name, 'michelangelo')
148
+ t.equal(res.statusCode, 200)
149
+ })
150
+
151
+ fastify.inject({
152
+ url: '/',
153
+ method: 'POST',
154
+ headers: { 'Content-Type': 'application/json' },
155
+ body: { name: 'michelangelo' }
156
+ }, (err, res) => {
157
+ t.error(err)
158
+ t.same(res.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: "body must have required property 'work'" })
159
+ t.equal(res.statusCode, 400)
160
+ })
161
+
162
+ fastify.inject({
163
+ url: '/',
164
+ method: 'POST',
165
+ headers: { 'Content-Type': 'application/octet-stream' },
166
+ body: Buffer.from('AAAAAAAA')
167
+ }, (err, res) => {
168
+ t.error(err)
169
+ t.same(res.payload, 'AAAAAAAA')
170
+ t.equal(res.statusCode, 200)
171
+ })
172
+
173
+ fastify.inject({
174
+ url: '/',
175
+ method: 'POST',
176
+ headers: { 'Content-Type': 'text/plain' },
177
+ body: 'AAAAAAAA'
178
+ }, (err, res) => {
179
+ t.error(err)
180
+ t.same(res.payload, 'AAAAAAAA')
181
+ t.equal(res.statusCode, 200)
182
+ })
183
+ })
184
+
185
+ test('Skip validation if no schema for content type', t => {
186
+ t.plan(3)
187
+
188
+ const fastify = Fastify()
189
+ fastify.post('/', {
190
+ schema: {
191
+ body: {
192
+ content: {
193
+ 'application/json': {
194
+ schema: schemaArtist
195
+ }
196
+ // No schema for 'text/plain'
197
+ }
198
+ }
199
+ }
200
+ }, async function (req, reply) {
201
+ return reply.send(req.body)
202
+ })
203
+
204
+ fastify.inject({
205
+ url: '/',
206
+ method: 'POST',
207
+ headers: { 'Content-Type': 'text/plain' },
208
+ body: 'AAAAAAAA'
209
+ }, (err, res) => {
210
+ t.error(err)
211
+ t.same(res.payload, 'AAAAAAAA')
212
+ t.equal(res.statusCode, 200)
213
+ })
214
+ })
215
+
216
+ test('Skip validation if no content type schemas', t => {
217
+ t.plan(3)
218
+
219
+ const fastify = Fastify()
220
+ fastify.post('/', {
221
+ schema: {
222
+ body: {
223
+ content: {
224
+ // No schemas
225
+ }
226
+ }
227
+ }
228
+ }, async function (req, reply) {
229
+ return reply.send(req.body)
230
+ })
231
+
232
+ fastify.inject({
233
+ url: '/',
234
+ method: 'POST',
235
+ headers: { 'Content-Type': 'text/plain' },
236
+ body: 'AAAAAAAA'
237
+ }, (err, res) => {
238
+ t.error(err)
239
+ t.same(res.payload, 'AAAAAAAA')
240
+ t.equal(res.statusCode, 200)
241
+ })
242
+ })
243
+
108
244
  test('External AJV instance', t => {
109
245
  t.plan(5)
110
246
 
@@ -0,0 +1,37 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const test = t.test
5
+ const Fastify = require('..')
6
+ const Reply = require('../lib/reply')
7
+
8
+ test('should serialize reply when response stream is ended', t => {
9
+ t.plan(3)
10
+ const stream = require('node:stream')
11
+ const fastify = Fastify({
12
+ logger: {
13
+ serializers: {
14
+ res (reply) {
15
+ t.type(reply, Reply)
16
+ return reply
17
+ }
18
+ }
19
+ }
20
+ })
21
+
22
+ fastify.get('/error', function (req, reply) {
23
+ const reallyLongStream = new stream.Readable({
24
+ read: () => { }
25
+ })
26
+ reply.code(200).send(reallyLongStream)
27
+ reply.raw.end(Buffer.from('hello\n'))
28
+ })
29
+
30
+ fastify.inject({
31
+ url: '/error',
32
+ method: 'GET'
33
+ }, (err) => {
34
+ t.error(err)
35
+ fastify.close()
36
+ })
37
+ })
@@ -22,9 +22,9 @@ test('Fastify should throw on multiple assignment to the same route', t => {
22
22
 
23
23
  try {
24
24
  fastify.get('/', () => {})
25
- t.fail('Should throw on duplicated route declaration')
25
+ t.fail('Should throw fastify duplicated route declaration')
26
26
  } catch (error) {
27
- t.equal(error.message, "Method 'GET' already declared for route '/'")
27
+ t.equal(error.code, 'FST_ERR_DUPLICATED_ROUTE')
28
28
  }
29
29
  })
30
30
 
@@ -151,7 +151,8 @@ server.addHook('onListen', function (done) {
151
151
  expectAssignable<(err?: NodeJS.ErrnoException) => void>(done)
152
152
  })
153
153
 
154
- server.addHook('onClose', (instance, done) => {
154
+ server.addHook('onClose', function (instance, done) {
155
+ expectType<FastifyInstance>(this)
155
156
  expectType<FastifyInstance>(instance)
156
157
  expectAssignable<(err?: FastifyError) => void>(done)
157
158
  expectAssignable<(err?: NodeJS.ErrnoException) => void>(done)
@@ -236,7 +237,8 @@ server.addHook('onListen', async function () {
236
237
  expectType<FastifyInstance>(this)
237
238
  })
238
239
 
239
- server.addHook('onClose', async (instance) => {
240
+ server.addHook('onClose', async function (instance) {
241
+ expectType<FastifyInstance>(this)
240
242
  expectType<FastifyInstance>(instance)
241
243
  })
242
244
 
@@ -19,6 +19,13 @@ declare module '../../fastify' {
19
19
  interface FastifyContextConfig {
20
20
  foo: string;
21
21
  bar: number;
22
+ includeMessage?: boolean;
23
+ }
24
+
25
+ interface FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider, ContextConfig, Logger, RequestType> {
26
+ message: ContextConfig extends { includeMessage: true }
27
+ ? string
28
+ : null;
22
29
  }
23
30
  }
24
31
 
@@ -36,6 +43,22 @@ const routeHandlerWithReturnValue: RouteHandlerMethod = function (request, reply
36
43
  return reply.send()
37
44
  }
38
45
 
46
+ fastify().get(
47
+ '/',
48
+ { config: { foo: 'bar', bar: 100, includeMessage: true } },
49
+ (req) => {
50
+ expectType<string>(req.message)
51
+ }
52
+ )
53
+
54
+ fastify().get(
55
+ '/',
56
+ { config: { foo: 'bar', bar: 100, includeMessage: false } },
57
+ (req) => {
58
+ expectType<null>(req.message)
59
+ }
60
+ )
61
+
39
62
  type LowerCaseHTTPMethods = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete' | 'options';
40
63
 
41
64
  ['GET', 'POST', 'PUT', 'PATCH', 'HEAD', 'DELETE', 'OPTIONS'].forEach(method => {
@@ -20,6 +20,25 @@ expectAssignable<FastifyInstance>(server.get(
20
20
  () => { }
21
21
  ))
22
22
 
23
+ expectAssignable<FastifyInstance>(server.post(
24
+ '/multiple-content-schema',
25
+ {
26
+ schema: {
27
+ body: {
28
+ content: {
29
+ 'application/json': {
30
+ schema: { type: 'object' }
31
+ },
32
+ 'text/plain': {
33
+ schema: { type: 'string' }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ },
39
+ () => { }
40
+ ))
41
+
23
42
  expectAssignable<FastifyInstance>(server.get(
24
43
  '/empty-schema',
25
44
  {