node-fastify 5.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/.borp.yaml +3 -0
  2. package/.markdownlint-cli2.yaml +22 -0
  3. package/.prettierignore +1 -0
  4. package/GOVERNANCE.md +4 -0
  5. package/LICENSE +21 -0
  6. package/PROJECT_CHARTER.md +126 -0
  7. package/README.md +423 -0
  8. package/SECURITY.md +220 -0
  9. package/SPONSORS.md +24 -0
  10. package/build/build-error-serializer.js +35 -0
  11. package/build/build-validation.js +169 -0
  12. package/build/sync-version.js +11 -0
  13. package/docs/Guides/Benchmarking.md +60 -0
  14. package/docs/Guides/Database.md +321 -0
  15. package/docs/Guides/Delay-Accepting-Requests.md +608 -0
  16. package/docs/Guides/Detecting-When-Clients-Abort.md +172 -0
  17. package/docs/Guides/Ecosystem.md +726 -0
  18. package/docs/Guides/Fluent-Schema.md +127 -0
  19. package/docs/Guides/Getting-Started.md +620 -0
  20. package/docs/Guides/Index.md +43 -0
  21. package/docs/Guides/Migration-Guide-V3.md +287 -0
  22. package/docs/Guides/Migration-Guide-V4.md +267 -0
  23. package/docs/Guides/Migration-Guide-V5.md +727 -0
  24. package/docs/Guides/Plugins-Guide.md +520 -0
  25. package/docs/Guides/Prototype-Poisoning.md +383 -0
  26. package/docs/Guides/Recommendations.md +378 -0
  27. package/docs/Guides/Serverless.md +604 -0
  28. package/docs/Guides/Style-Guide.md +246 -0
  29. package/docs/Guides/Testing.md +481 -0
  30. package/docs/Guides/Write-Plugin.md +103 -0
  31. package/docs/Guides/Write-Type-Provider.md +34 -0
  32. package/docs/Reference/ContentTypeParser.md +271 -0
  33. package/docs/Reference/Decorators.md +436 -0
  34. package/docs/Reference/Encapsulation.md +194 -0
  35. package/docs/Reference/Errors.md +377 -0
  36. package/docs/Reference/HTTP2.md +94 -0
  37. package/docs/Reference/Hooks.md +958 -0
  38. package/docs/Reference/Index.md +73 -0
  39. package/docs/Reference/LTS.md +86 -0
  40. package/docs/Reference/Lifecycle.md +99 -0
  41. package/docs/Reference/Logging.md +268 -0
  42. package/docs/Reference/Middleware.md +79 -0
  43. package/docs/Reference/Plugins.md +245 -0
  44. package/docs/Reference/Principles.md +73 -0
  45. package/docs/Reference/Reply.md +1001 -0
  46. package/docs/Reference/Request.md +295 -0
  47. package/docs/Reference/Routes.md +802 -0
  48. package/docs/Reference/Server.md +2389 -0
  49. package/docs/Reference/Type-Providers.md +256 -0
  50. package/docs/Reference/TypeScript.md +1729 -0
  51. package/docs/Reference/Validation-and-Serialization.md +1130 -0
  52. package/docs/Reference/Warnings.md +58 -0
  53. package/docs/index.md +24 -0
  54. package/docs/resources/encapsulation_context.drawio +1 -0
  55. package/docs/resources/encapsulation_context.svg +3 -0
  56. package/eslint.config.js +35 -0
  57. package/examples/asyncawait.js +38 -0
  58. package/examples/benchmark/body.json +3 -0
  59. package/examples/benchmark/hooks-benchmark-async-await.js +44 -0
  60. package/examples/benchmark/hooks-benchmark.js +52 -0
  61. package/examples/benchmark/parser.js +47 -0
  62. package/examples/benchmark/simple.js +30 -0
  63. package/examples/benchmark/webstream.js +27 -0
  64. package/examples/hooks.js +91 -0
  65. package/examples/http2.js +39 -0
  66. package/examples/https.js +38 -0
  67. package/examples/parser.js +53 -0
  68. package/examples/plugin.js +12 -0
  69. package/examples/route-prefix.js +38 -0
  70. package/examples/shared-schema.js +38 -0
  71. package/examples/simple-stream.js +20 -0
  72. package/examples/simple.js +32 -0
  73. package/examples/simple.mjs +27 -0
  74. package/examples/typescript-server.ts +79 -0
  75. package/examples/use-plugin.js +29 -0
  76. package/fastify.d.ts +253 -0
  77. package/fastify.js +985 -0
  78. package/integration/server.js +29 -0
  79. package/integration/test.sh +23 -0
  80. package/lib/config-validator.js +1266 -0
  81. package/lib/content-type-parser.js +413 -0
  82. package/lib/content-type.js +160 -0
  83. package/lib/context.js +98 -0
  84. package/lib/decorate.js +152 -0
  85. package/lib/error-handler.js +173 -0
  86. package/lib/error-serializer.js +134 -0
  87. package/lib/error-status.js +14 -0
  88. package/lib/errors.js +516 -0
  89. package/lib/four-oh-four.js +190 -0
  90. package/lib/handle-request.js +195 -0
  91. package/lib/head-route.js +45 -0
  92. package/lib/hooks.js +429 -0
  93. package/lib/initial-config-validation.js +37 -0
  94. package/lib/logger-factory.js +136 -0
  95. package/lib/logger-pino.js +68 -0
  96. package/lib/noop-set.js +10 -0
  97. package/lib/plugin-override.js +90 -0
  98. package/lib/plugin-utils.js +169 -0
  99. package/lib/promise.js +23 -0
  100. package/lib/reply.js +1030 -0
  101. package/lib/req-id-gen-factory.js +52 -0
  102. package/lib/request.js +391 -0
  103. package/lib/route.js +686 -0
  104. package/lib/schema-controller.js +164 -0
  105. package/lib/schemas.js +207 -0
  106. package/lib/server.js +441 -0
  107. package/lib/symbols.js +71 -0
  108. package/lib/validation.js +280 -0
  109. package/lib/warnings.js +57 -0
  110. package/lib/wrap-thenable.js +84 -0
  111. package/package.json +225 -0
  112. package/scripts/validate-ecosystem-links.js +179 -0
  113. package/test/404s.test.js +2035 -0
  114. package/test/500s.test.js +422 -0
  115. package/test/allow-unsafe-regex.test.js +92 -0
  116. package/test/als.test.js +65 -0
  117. package/test/async-await.test.js +705 -0
  118. package/test/async-dispose.test.js +20 -0
  119. package/test/async_hooks.test.js +52 -0
  120. package/test/body-limit.test.js +224 -0
  121. package/test/buffer.test.js +74 -0
  122. package/test/build/error-serializer.test.js +36 -0
  123. package/test/build/version.test.js +14 -0
  124. package/test/build-certificate.js +109 -0
  125. package/test/bundler/README.md +29 -0
  126. package/test/bundler/esbuild/bundler-test.js +32 -0
  127. package/test/bundler/esbuild/package.json +10 -0
  128. package/test/bundler/esbuild/src/fail-plugin-version.js +14 -0
  129. package/test/bundler/esbuild/src/index.js +9 -0
  130. package/test/bundler/webpack/bundler-test.js +32 -0
  131. package/test/bundler/webpack/package.json +11 -0
  132. package/test/bundler/webpack/src/fail-plugin-version.js +14 -0
  133. package/test/bundler/webpack/src/index.js +9 -0
  134. package/test/bundler/webpack/webpack.config.js +15 -0
  135. package/test/case-insensitive.test.js +102 -0
  136. package/test/chainable.test.js +40 -0
  137. package/test/child-logger-factory.test.js +128 -0
  138. package/test/client-timeout.test.js +38 -0
  139. package/test/close-pipelining.test.js +78 -0
  140. package/test/close.test.js +706 -0
  141. package/test/conditional-pino.test.js +47 -0
  142. package/test/connection-timeout.test.js +42 -0
  143. package/test/constrained-routes.test.js +1138 -0
  144. package/test/content-length.test.js +174 -0
  145. package/test/content-parser.test.js +739 -0
  146. package/test/content-type.test.js +181 -0
  147. package/test/context-config.test.js +164 -0
  148. package/test/custom-http-server.test.js +118 -0
  149. package/test/custom-parser-async.test.js +59 -0
  150. package/test/custom-parser.0.test.js +701 -0
  151. package/test/custom-parser.1.test.js +266 -0
  152. package/test/custom-parser.2.test.js +91 -0
  153. package/test/custom-parser.3.test.js +208 -0
  154. package/test/custom-parser.4.test.js +218 -0
  155. package/test/custom-parser.5.test.js +130 -0
  156. package/test/custom-querystring-parser.test.js +129 -0
  157. package/test/decorator.test.js +1330 -0
  158. package/test/delete.test.js +344 -0
  159. package/test/diagnostics-channel/404.test.js +49 -0
  160. package/test/diagnostics-channel/async-delay-request.test.js +65 -0
  161. package/test/diagnostics-channel/async-request.test.js +64 -0
  162. package/test/diagnostics-channel/error-before-handler.test.js +35 -0
  163. package/test/diagnostics-channel/error-request.test.js +53 -0
  164. package/test/diagnostics-channel/error-status.test.js +123 -0
  165. package/test/diagnostics-channel/init.test.js +50 -0
  166. package/test/diagnostics-channel/sync-delay-request.test.js +49 -0
  167. package/test/diagnostics-channel/sync-request-reply.test.js +51 -0
  168. package/test/diagnostics-channel/sync-request.test.js +54 -0
  169. package/test/encapsulated-child-logger-factory.test.js +69 -0
  170. package/test/encapsulated-error-handler.test.js +237 -0
  171. package/test/esm/errorCodes.test.mjs +10 -0
  172. package/test/esm/esm.test.mjs +13 -0
  173. package/test/esm/index.test.js +8 -0
  174. package/test/esm/named-exports.mjs +14 -0
  175. package/test/esm/other.mjs +8 -0
  176. package/test/esm/plugin.mjs +8 -0
  177. package/test/fastify-instance.test.js +300 -0
  178. package/test/find-route.test.js +152 -0
  179. package/test/fluent-schema.test.js +209 -0
  180. package/test/genReqId.test.js +426 -0
  181. package/test/handler-context.test.js +45 -0
  182. package/test/handler-timeout.test.js +367 -0
  183. package/test/has-route.test.js +88 -0
  184. package/test/header-overflow.test.js +55 -0
  185. package/test/helper.js +496 -0
  186. package/test/hooks-async.test.js +1099 -0
  187. package/test/hooks.on-listen.test.js +1162 -0
  188. package/test/hooks.on-ready.test.js +421 -0
  189. package/test/hooks.test.js +3578 -0
  190. package/test/http-methods/copy.test.js +35 -0
  191. package/test/http-methods/custom-http-methods.test.js +114 -0
  192. package/test/http-methods/get.test.js +412 -0
  193. package/test/http-methods/head.test.js +263 -0
  194. package/test/http-methods/lock.test.js +108 -0
  195. package/test/http-methods/mkcalendar.test.js +143 -0
  196. package/test/http-methods/mkcol.test.js +35 -0
  197. package/test/http-methods/move.test.js +42 -0
  198. package/test/http-methods/propfind.test.js +136 -0
  199. package/test/http-methods/proppatch.test.js +105 -0
  200. package/test/http-methods/report.test.js +142 -0
  201. package/test/http-methods/search.test.js +233 -0
  202. package/test/http-methods/trace.test.js +21 -0
  203. package/test/http-methods/unlock.test.js +38 -0
  204. package/test/http2/closing.test.js +270 -0
  205. package/test/http2/constraint.test.js +109 -0
  206. package/test/http2/head.test.js +34 -0
  207. package/test/http2/plain.test.js +68 -0
  208. package/test/http2/secure-with-fallback.test.js +113 -0
  209. package/test/http2/secure.test.js +67 -0
  210. package/test/http2/unknown-http-method.test.js +34 -0
  211. package/test/https/custom-https-server.test.js +58 -0
  212. package/test/https/https.test.js +136 -0
  213. package/test/imports.test.js +17 -0
  214. package/test/inject.test.js +502 -0
  215. package/test/input-validation.js +335 -0
  216. package/test/internals/all.test.js +38 -0
  217. package/test/internals/content-type-parser.test.js +111 -0
  218. package/test/internals/context.test.js +31 -0
  219. package/test/internals/decorator.test.js +156 -0
  220. package/test/internals/errors.test.js +982 -0
  221. package/test/internals/handle-request.test.js +270 -0
  222. package/test/internals/hook-runner.test.js +449 -0
  223. package/test/internals/hooks.test.js +96 -0
  224. package/test/internals/initial-config.test.js +383 -0
  225. package/test/internals/logger.test.js +163 -0
  226. package/test/internals/plugin.test.js +170 -0
  227. package/test/internals/promise.test.js +63 -0
  228. package/test/internals/reply-serialize.test.js +714 -0
  229. package/test/internals/reply.test.js +1920 -0
  230. package/test/internals/req-id-gen-factory.test.js +133 -0
  231. package/test/internals/request-validate.test.js +1402 -0
  232. package/test/internals/request.test.js +506 -0
  233. package/test/internals/schema-controller-perf.test.js +40 -0
  234. package/test/internals/server.test.js +91 -0
  235. package/test/internals/validation.test.js +352 -0
  236. package/test/issue-4959.test.js +118 -0
  237. package/test/keep-alive-timeout.test.js +42 -0
  238. package/test/listen.1.test.js +154 -0
  239. package/test/listen.2.test.js +113 -0
  240. package/test/listen.3.test.js +83 -0
  241. package/test/listen.4.test.js +168 -0
  242. package/test/listen.5.test.js +122 -0
  243. package/test/logger/instantiation.test.js +341 -0
  244. package/test/logger/logger-test-utils.js +47 -0
  245. package/test/logger/logging.test.js +460 -0
  246. package/test/logger/options.test.js +579 -0
  247. package/test/logger/request.test.js +292 -0
  248. package/test/logger/response.test.js +183 -0
  249. package/test/logger/tap-parallel-not-ok +0 -0
  250. package/test/max-requests-per-socket.test.js +113 -0
  251. package/test/middleware.test.js +37 -0
  252. package/test/noop-set.test.js +19 -0
  253. package/test/nullable-validation.test.js +187 -0
  254. package/test/options.error-handler.test.js +5 -0
  255. package/test/options.test.js +5 -0
  256. package/test/output-validation.test.js +140 -0
  257. package/test/patch.error-handler.test.js +5 -0
  258. package/test/patch.test.js +5 -0
  259. package/test/plugin.1.test.js +230 -0
  260. package/test/plugin.2.test.js +314 -0
  261. package/test/plugin.3.test.js +287 -0
  262. package/test/plugin.4.test.js +504 -0
  263. package/test/plugin.helper.js +8 -0
  264. package/test/plugin.name.display.js +10 -0
  265. package/test/post-empty-body.test.js +38 -0
  266. package/test/pretty-print.test.js +366 -0
  267. package/test/promises.test.js +125 -0
  268. package/test/proto-poisoning.test.js +145 -0
  269. package/test/put.error-handler.test.js +5 -0
  270. package/test/put.test.js +5 -0
  271. package/test/register.test.js +184 -0
  272. package/test/reply-code.test.js +148 -0
  273. package/test/reply-early-hints.test.js +100 -0
  274. package/test/reply-error.test.js +815 -0
  275. package/test/reply-trailers.test.js +445 -0
  276. package/test/reply-web-stream-locked.test.js +37 -0
  277. package/test/request-error.test.js +624 -0
  278. package/test/request-header-host.test.js +339 -0
  279. package/test/request-id.test.js +118 -0
  280. package/test/request-timeout.test.js +53 -0
  281. package/test/route-hooks.test.js +635 -0
  282. package/test/route-prefix.test.js +904 -0
  283. package/test/route-shorthand.test.js +48 -0
  284. package/test/route.1.test.js +259 -0
  285. package/test/route.2.test.js +100 -0
  286. package/test/route.3.test.js +213 -0
  287. package/test/route.4.test.js +127 -0
  288. package/test/route.5.test.js +211 -0
  289. package/test/route.6.test.js +306 -0
  290. package/test/route.7.test.js +406 -0
  291. package/test/route.8.test.js +225 -0
  292. package/test/router-options.test.js +1108 -0
  293. package/test/same-shape.test.js +124 -0
  294. package/test/schema-examples.test.js +661 -0
  295. package/test/schema-feature.test.js +2198 -0
  296. package/test/schema-serialization.test.js +1171 -0
  297. package/test/schema-special-usage.test.js +1348 -0
  298. package/test/schema-validation.test.js +1572 -0
  299. package/test/scripts/validate-ecosystem-links.test.js +339 -0
  300. package/test/serialize-response.test.js +186 -0
  301. package/test/server.test.js +347 -0
  302. package/test/set-error-handler.test.js +69 -0
  303. package/test/skip-reply-send.test.js +317 -0
  304. package/test/stream-serializers.test.js +40 -0
  305. package/test/stream.1.test.js +94 -0
  306. package/test/stream.2.test.js +129 -0
  307. package/test/stream.3.test.js +198 -0
  308. package/test/stream.4.test.js +176 -0
  309. package/test/stream.5.test.js +188 -0
  310. package/test/sync-routes.test.js +32 -0
  311. package/test/throw.test.js +359 -0
  312. package/test/toolkit.js +63 -0
  313. package/test/trust-proxy.test.js +162 -0
  314. package/test/type-provider.test.js +22 -0
  315. package/test/types/content-type-parser.test-d.ts +72 -0
  316. package/test/types/decorate-request-reply.test-d.ts +18 -0
  317. package/test/types/dummy-plugin.ts +9 -0
  318. package/test/types/errors.test-d.ts +90 -0
  319. package/test/types/fastify.test-d.ts +352 -0
  320. package/test/types/hooks.test-d.ts +550 -0
  321. package/test/types/import.ts +2 -0
  322. package/test/types/instance.test-d.ts +588 -0
  323. package/test/types/logger.test-d.ts +277 -0
  324. package/test/types/plugin.test-d.ts +97 -0
  325. package/test/types/register.test-d.ts +237 -0
  326. package/test/types/reply.test-d.ts +254 -0
  327. package/test/types/request.test-d.ts +188 -0
  328. package/test/types/route.test-d.ts +553 -0
  329. package/test/types/schema.test-d.ts +135 -0
  330. package/test/types/serverFactory.test-d.ts +37 -0
  331. package/test/types/type-provider.test-d.ts +1213 -0
  332. package/test/types/using.test-d.ts +17 -0
  333. package/test/upgrade.test.js +52 -0
  334. package/test/url-rewriting.test.js +122 -0
  335. package/test/use-semicolon-delimiter.test.js +168 -0
  336. package/test/validation-error-handling.test.js +900 -0
  337. package/test/versioned-routes.test.js +603 -0
  338. package/test/web-api.test.js +616 -0
  339. package/test/wrap-thenable.test.js +30 -0
  340. package/types/content-type-parser.d.ts +75 -0
  341. package/types/context.d.ts +22 -0
  342. package/types/errors.d.ts +92 -0
  343. package/types/hooks.d.ts +875 -0
  344. package/types/instance.d.ts +609 -0
  345. package/types/logger.d.ts +107 -0
  346. package/types/plugin.d.ts +44 -0
  347. package/types/register.d.ts +42 -0
  348. package/types/reply.d.ts +81 -0
  349. package/types/request.d.ts +95 -0
  350. package/types/route.d.ts +199 -0
  351. package/types/schema.d.ts +61 -0
  352. package/types/server-factory.d.ts +19 -0
  353. package/types/type-provider.d.ts +130 -0
  354. package/types/utils.d.ts +98 -0
@@ -0,0 +1,344 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const fastify = require('..')()
5
+
6
+ const schema = {
7
+ schema: {
8
+ response: {
9
+ '2xx': {
10
+ type: 'object',
11
+ properties: {
12
+ hello: {
13
+ type: 'string'
14
+ }
15
+ }
16
+ }
17
+ }
18
+ }
19
+ }
20
+
21
+ const querySchema = {
22
+ schema: {
23
+ querystring: {
24
+ type: 'object',
25
+ properties: {
26
+ hello: {
27
+ type: 'integer'
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ const paramsSchema = {
35
+ schema: {
36
+ params: {
37
+ type: 'object',
38
+ properties: {
39
+ foo: {
40
+ type: 'string'
41
+ },
42
+ test: {
43
+ type: 'integer'
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+
50
+ const headersSchema = {
51
+ schema: {
52
+ headers: {
53
+ type: 'object',
54
+ properties: {
55
+ 'x-test': {
56
+ type: 'number'
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+
63
+ const bodySchema = {
64
+ schema: {
65
+ body: {
66
+ type: 'object',
67
+ properties: {
68
+ hello: {
69
+ type: 'string'
70
+ }
71
+ }
72
+ },
73
+ response: {
74
+ '2xx': {
75
+ type: 'object',
76
+ properties: {
77
+ hello: {
78
+ type: 'string'
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ test('shorthand - delete', (t, done) => {
87
+ t.plan(1)
88
+ try {
89
+ fastify.delete('/', schema, function (req, reply) {
90
+ reply.code(200).send({ hello: 'world' })
91
+ })
92
+ t.assert.ok(true)
93
+ } catch (e) {
94
+ t.assert.fail()
95
+ } finally {
96
+ done()
97
+ }
98
+ })
99
+
100
+ test('shorthand - delete params', t => {
101
+ t.plan(1)
102
+ try {
103
+ fastify.delete('/params/:foo/:test', paramsSchema, function (req, reply) {
104
+ reply.code(200).send(req.params)
105
+ })
106
+ t.assert.ok(true)
107
+ } catch (e) {
108
+ t.assert.fail()
109
+ }
110
+ })
111
+
112
+ test('shorthand - delete, querystring schema', t => {
113
+ t.plan(1)
114
+ try {
115
+ fastify.delete('/query', querySchema, function (req, reply) {
116
+ reply.send(req.query)
117
+ })
118
+ t.assert.ok(true)
119
+ } catch (e) {
120
+ t.assert.fail()
121
+ }
122
+ })
123
+
124
+ test('shorthand - get, headers schema', t => {
125
+ t.plan(1)
126
+ try {
127
+ fastify.delete('/headers', headersSchema, function (req, reply) {
128
+ reply.code(200).send(req.headers)
129
+ })
130
+ t.assert.ok(true)
131
+ } catch (e) {
132
+ t.assert.fail()
133
+ }
134
+ })
135
+
136
+ test('missing schema - delete', t => {
137
+ t.plan(1)
138
+ try {
139
+ fastify.delete('/missing', function (req, reply) {
140
+ reply.code(200).send({ hello: 'world' })
141
+ })
142
+ t.assert.ok(true)
143
+ } catch (e) {
144
+ t.assert.fail()
145
+ }
146
+ })
147
+
148
+ test('body - delete', t => {
149
+ t.plan(1)
150
+ try {
151
+ fastify.delete('/body', bodySchema, function (req, reply) {
152
+ reply.send(req.body)
153
+ })
154
+ t.assert.ok(true)
155
+ } catch (e) {
156
+ t.assert.fail()
157
+ }
158
+ })
159
+
160
+ test('delete tests', async t => {
161
+ const fastifyServer = await fastify.listen({ port: 0 })
162
+ t.after(() => { fastify.close() })
163
+
164
+ await t.test('shorthand - request delete', async t => {
165
+ t.plan(4)
166
+
167
+ const response = await fetch(fastifyServer, {
168
+ method: 'DELETE'
169
+ })
170
+ t.assert.ok(response.ok)
171
+ t.assert.strictEqual(response.status, 200)
172
+ const body = await response.text()
173
+ t.assert.strictEqual(response.headers.get('content-length'), '' + body.length)
174
+ t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
175
+ })
176
+
177
+ await t.test('shorthand - request delete params schema', async t => {
178
+ t.plan(4)
179
+
180
+ const response = await fetch(fastifyServer + '/params/world/123', {
181
+ method: 'DELETE'
182
+ })
183
+ t.assert.ok(response.ok)
184
+ t.assert.strictEqual(response.status, 200)
185
+ const body = await response.text()
186
+ t.assert.strictEqual(response.headers.get('content-length'), '' + body.length)
187
+ t.assert.deepStrictEqual(JSON.parse(body), { foo: 'world', test: 123 })
188
+ })
189
+
190
+ await t.test('shorthand - request delete params schema error', async t => {
191
+ t.plan(3)
192
+
193
+ const response = await fetch(fastifyServer + '/params/world/string', {
194
+ method: 'DELETE'
195
+ })
196
+
197
+ t.assert.ok(!response.ok)
198
+ t.assert.strictEqual(response.status, 400)
199
+ t.assert.deepStrictEqual(await response.json(), {
200
+ error: 'Bad Request',
201
+ code: 'FST_ERR_VALIDATION',
202
+ message: 'params/test must be integer',
203
+ statusCode: 400
204
+ })
205
+ })
206
+
207
+ await t.test('shorthand - request delete headers schema', async t => {
208
+ t.plan(4)
209
+
210
+ const response = await fetch(fastifyServer + '/headers', {
211
+ method: 'DELETE',
212
+ headers: {
213
+ 'x-test': '1'
214
+ }
215
+ })
216
+ t.assert.ok(response.ok)
217
+ t.assert.strictEqual(response.status, 200)
218
+ const body = await response.text()
219
+ t.assert.strictEqual(response.headers.get('content-length'), '' + body.length)
220
+ t.assert.strictEqual(JSON.parse(body)['x-test'], 1)
221
+ })
222
+
223
+ await t.test('shorthand - request delete headers schema error', async t => {
224
+ t.plan(3)
225
+
226
+ const response = await fetch(fastifyServer + '/headers', {
227
+ method: 'DELETE',
228
+ headers: {
229
+ 'x-test': 'abc'
230
+ }
231
+ })
232
+
233
+ t.assert.ok(!response.ok)
234
+ t.assert.strictEqual(response.status, 400)
235
+ const body = await response.text()
236
+ t.assert.deepStrictEqual(JSON.parse(body), {
237
+ error: 'Bad Request',
238
+ code: 'FST_ERR_VALIDATION',
239
+ message: 'headers/x-test must be number',
240
+ statusCode: 400
241
+ })
242
+ })
243
+
244
+ await t.test('shorthand - request delete querystring schema', async t => {
245
+ t.plan(4)
246
+
247
+ const response = await fetch(fastifyServer + '/query?hello=123', {
248
+ method: 'DELETE'
249
+ })
250
+ t.assert.ok(response.ok)
251
+ t.assert.strictEqual(response.status, 200)
252
+ const body = await response.text()
253
+ t.assert.strictEqual(response.headers.get('content-length'), '' + body.length)
254
+ t.assert.deepStrictEqual(JSON.parse(body), { hello: 123 })
255
+ })
256
+
257
+ await t.test('shorthand - request delete querystring schema error', async t => {
258
+ t.plan(3)
259
+
260
+ const response = await fetch(fastifyServer + '/query?hello=world', {
261
+ method: 'DELETE'
262
+ })
263
+
264
+ t.assert.ok(!response.ok)
265
+ t.assert.strictEqual(response.status, 400)
266
+ const body = await response.text()
267
+ t.assert.deepStrictEqual(JSON.parse(body), {
268
+ error: 'Bad Request',
269
+ code: 'FST_ERR_VALIDATION',
270
+ message: 'querystring/hello must be integer',
271
+ statusCode: 400
272
+ })
273
+ })
274
+
275
+ await t.test('shorthand - request delete missing schema', async t => {
276
+ t.plan(4)
277
+
278
+ const response = await fetch(fastifyServer + '/missing', {
279
+ method: 'DELETE'
280
+ })
281
+ t.assert.ok(response.ok)
282
+ t.assert.strictEqual(response.status, 200)
283
+ const body = await response.text()
284
+ t.assert.strictEqual(response.headers.get('content-length'), '' + body.length)
285
+ t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
286
+ })
287
+
288
+ await t.test('shorthand - delete with body', async t => {
289
+ t.plan(3)
290
+
291
+ const response = await fetch(fastifyServer + '/body', {
292
+ method: 'DELETE',
293
+ body: JSON.stringify({ hello: 'world' }),
294
+ headers: {
295
+ 'Content-Type': 'application/json'
296
+ }
297
+ })
298
+ t.assert.ok(response.ok)
299
+ t.assert.strictEqual(response.status, 200)
300
+ const body = await response.json()
301
+ t.assert.deepStrictEqual(body, { hello: 'world' })
302
+ })
303
+ })
304
+
305
+ test('shorthand - delete with application/json Content-Type header and null body', (t, done) => {
306
+ t.plan(4)
307
+ const fastify = require('..')()
308
+ fastify.delete('/', {}, (req, reply) => {
309
+ t.assert.strictEqual(req.body, null)
310
+ reply.send(req.body)
311
+ })
312
+ fastify.inject({
313
+ method: 'DELETE',
314
+ url: '/',
315
+ headers: { 'Content-Type': 'application/json' },
316
+ body: 'null'
317
+ }, (err, response) => {
318
+ t.assert.ifError(err)
319
+ t.assert.strictEqual(response.statusCode, 200)
320
+ t.assert.strictEqual(response.payload.toString(), 'null')
321
+ done()
322
+ })
323
+ })
324
+
325
+ // https://github.com/fastify/fastify/issues/936
326
+ // Skip this test because this is an invalid request
327
+ test('shorthand - delete with application/json Content-Type header and without body', { skip: 'https://github.com/fastify/fastify/pull/5419' }, t => {
328
+ t.plan(4)
329
+ const fastify = require('..')()
330
+ fastify.delete('/', {}, (req, reply) => {
331
+ t.assert.strictEqual(req.body, undefined)
332
+ reply.send(req.body)
333
+ })
334
+ fastify.inject({
335
+ method: 'DELETE',
336
+ url: '/',
337
+ headers: { 'Content-Type': 'application/json' },
338
+ body: null
339
+ }, (err, response) => {
340
+ t.assert.ifError(err)
341
+ t.assert.strictEqual(response.statusCode, 200)
342
+ t.assert.strictEqual(response.payload.toString(), '')
343
+ })
344
+ })
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const diagnostics = require('node:diagnostics_channel')
5
+ const Fastify = require('../..')
6
+ const Request = require('../../lib/request')
7
+ const Reply = require('../../lib/reply')
8
+
9
+ test('diagnostics channel sync events fire in expected order', async t => {
10
+ t.plan(9)
11
+ let callOrder = 0
12
+ let firstEncounteredMessage
13
+
14
+ diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
15
+ t.assert.strictEqual(callOrder++, 0)
16
+ firstEncounteredMessage = msg
17
+ t.assert.ok(msg.request instanceof Request)
18
+ t.assert.ok(msg.reply instanceof Reply)
19
+ })
20
+
21
+ diagnostics.subscribe('tracing:fastify.request.handler:end', (msg) => {
22
+ t.assert.ok(msg.request instanceof Request)
23
+ t.assert.ok(msg.reply instanceof Reply)
24
+ t.assert.strictEqual(callOrder++, 1)
25
+ t.assert.strictEqual(msg, firstEncounteredMessage)
26
+ })
27
+
28
+ diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
29
+ t.assert.fail('should not trigger error channel')
30
+ })
31
+
32
+ const fastify = Fastify()
33
+ fastify.route({
34
+ method: 'GET',
35
+ url: '/',
36
+ handler: function (req, reply) {
37
+ reply.callNotFound()
38
+ }
39
+ })
40
+
41
+ const fastifyServer = await fastify.listen({ port: 0 })
42
+ t.after(() => { fastify.close() })
43
+
44
+ const response = await fetch(fastifyServer, {
45
+ method: 'GET'
46
+ })
47
+ t.assert.ok(!response.ok)
48
+ t.assert.strictEqual(response.status, 404)
49
+ })
@@ -0,0 +1,65 @@
1
+ 'use strict'
2
+
3
+ const diagnostics = require('node:diagnostics_channel')
4
+ const { test } = require('node:test')
5
+ const Fastify = require('../..')
6
+ const Request = require('../../lib/request')
7
+ const Reply = require('../../lib/reply')
8
+
9
+ test('diagnostics channel async events fire in expected order', async t => {
10
+ t.plan(19)
11
+ let callOrder = 0
12
+ let firstEncounteredMessage
13
+
14
+ diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
15
+ t.assert.strictEqual(callOrder++, 0)
16
+ firstEncounteredMessage = msg
17
+ t.assert.ok(msg.request instanceof Request)
18
+ t.assert.ok(msg.reply instanceof Reply)
19
+ })
20
+
21
+ diagnostics.subscribe('tracing:fastify.request.handler:end', (msg) => {
22
+ t.assert.strictEqual(callOrder++, 1)
23
+ t.assert.ok(msg.request instanceof Request)
24
+ t.assert.ok(msg.reply instanceof Reply)
25
+ t.assert.strictEqual(msg, firstEncounteredMessage)
26
+ t.assert.strictEqual(msg.async, true)
27
+ })
28
+
29
+ diagnostics.subscribe('tracing:fastify.request.handler:asyncStart', (msg) => {
30
+ t.assert.strictEqual(callOrder++, 2)
31
+ t.assert.ok(msg.request instanceof Request)
32
+ t.assert.ok(msg.reply instanceof Reply)
33
+ t.assert.strictEqual(msg, firstEncounteredMessage)
34
+ })
35
+
36
+ diagnostics.subscribe('tracing:fastify.request.handler:asyncEnd', (msg) => {
37
+ t.assert.strictEqual(callOrder++, 3)
38
+ t.assert.ok(msg.request instanceof Request)
39
+ t.assert.ok(msg.reply instanceof Reply)
40
+ t.assert.strictEqual(msg, firstEncounteredMessage)
41
+ })
42
+
43
+ diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
44
+ t.assert.fail('should not trigger error channel')
45
+ })
46
+
47
+ const fastify = Fastify()
48
+ fastify.route({
49
+ method: 'GET',
50
+ url: '/',
51
+ handler: async function (req, reply) {
52
+ setImmediate(() => reply.send({ hello: 'world' }))
53
+ return reply
54
+ }
55
+ })
56
+
57
+ t.after(() => { fastify.close() })
58
+
59
+ const fastifyServer = await fastify.listen({ port: 0 })
60
+
61
+ const result = await fetch(fastifyServer + '/')
62
+ t.assert.ok(result.ok)
63
+ t.assert.strictEqual(result.status, 200)
64
+ t.assert.deepStrictEqual(await result.json(), { hello: 'world' })
65
+ })
@@ -0,0 +1,64 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const diagnostics = require('node:diagnostics_channel')
5
+ const Fastify = require('../..')
6
+ const Request = require('../../lib/request')
7
+ const Reply = require('../../lib/reply')
8
+
9
+ test('diagnostics channel async events fire in expected order', async t => {
10
+ t.plan(18)
11
+ let callOrder = 0
12
+ let firstEncounteredMessage
13
+
14
+ diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
15
+ t.assert.strictEqual(callOrder++, 0)
16
+ firstEncounteredMessage = msg
17
+ t.assert.ok(msg.request instanceof Request)
18
+ t.assert.ok(msg.reply instanceof Reply)
19
+ })
20
+
21
+ diagnostics.subscribe('tracing:fastify.request.handler:end', (msg) => {
22
+ t.assert.strictEqual(callOrder++, 1)
23
+ t.assert.ok(msg.request instanceof Request)
24
+ t.assert.ok(msg.reply instanceof Reply)
25
+ t.assert.strictEqual(msg, firstEncounteredMessage)
26
+ })
27
+
28
+ diagnostics.subscribe('tracing:fastify.request.handler:asyncStart', (msg) => {
29
+ t.assert.strictEqual(callOrder++, 2)
30
+ t.assert.ok(msg.request instanceof Request)
31
+ t.assert.ok(msg.reply instanceof Reply)
32
+ t.assert.strictEqual(msg, firstEncounteredMessage)
33
+ })
34
+
35
+ diagnostics.subscribe('tracing:fastify.request.handler:asyncEnd', (msg) => {
36
+ t.assert.strictEqual(callOrder++, 3)
37
+ t.assert.ok(msg.request instanceof Request)
38
+ t.assert.ok(msg.reply instanceof Reply)
39
+ t.assert.strictEqual(msg, firstEncounteredMessage)
40
+ })
41
+
42
+ diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
43
+ t.assert.fail('should not trigger error channel')
44
+ })
45
+
46
+ const fastify = Fastify()
47
+ fastify.route({
48
+ method: 'GET',
49
+ url: '/',
50
+ handler: async function (req, reply) {
51
+ return { hello: 'world' }
52
+ }
53
+ })
54
+
55
+ const fastifyServer = await fastify.listen({ port: 0 })
56
+
57
+ t.after(() => { fastify.close() })
58
+
59
+ const response = await fetch(fastifyServer)
60
+ t.assert.ok(response.ok)
61
+ t.assert.strictEqual(response.status, 200)
62
+ const body = await response.text()
63
+ t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
64
+ })
@@ -0,0 +1,35 @@
1
+ 'use strict'
2
+
3
+ const diagnostics = require('node:diagnostics_channel')
4
+ const { test } = require('node:test')
5
+ require('../../lib/hooks').onSendHookRunner = function Stub () {}
6
+ const Request = require('../../lib/request')
7
+ const Reply = require('../../lib/reply')
8
+ const symbols = require('../../lib/symbols.js')
9
+ const { preHandlerCallback } = require('../../lib/handle-request')[Symbol.for('internals')]
10
+
11
+ test('diagnostics channel handles an error before calling context handler', t => {
12
+ t.plan(3)
13
+ let callOrder = 0
14
+
15
+ diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
16
+ t.assert.strictEqual(callOrder++, 0)
17
+ })
18
+
19
+ diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
20
+ t.assert.strictEqual(callOrder++, 1)
21
+ t.assert.strictEqual(msg.error.message, 'oh no')
22
+ })
23
+
24
+ const error = new Error('oh no')
25
+ const request = new Request()
26
+ const reply = new Reply({}, request)
27
+ request[symbols.kRouteContext] = {
28
+ config: {
29
+ url: '/foo',
30
+ method: 'GET'
31
+ }
32
+ }
33
+
34
+ preHandlerCallback(error, request, reply)
35
+ })
@@ -0,0 +1,53 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const diagnostics = require('node:diagnostics_channel')
5
+ const Fastify = require('../..')
6
+ const Request = require('../../lib/request')
7
+ const Reply = require('../../lib/reply')
8
+
9
+ test('diagnostics channel events report on errors', async t => {
10
+ t.plan(14)
11
+ let callOrder = 0
12
+ let firstEncounteredMessage
13
+
14
+ diagnostics.subscribe('tracing:fastify.request.handler:start', (msg) => {
15
+ t.assert.strictEqual(callOrder++, 0)
16
+ firstEncounteredMessage = msg
17
+ t.assert.ok(msg.request instanceof Request)
18
+ t.assert.ok(msg.reply instanceof Reply)
19
+ })
20
+
21
+ diagnostics.subscribe('tracing:fastify.request.handler:end', (msg) => {
22
+ t.assert.ok(msg.request instanceof Request)
23
+ t.assert.ok(msg.reply instanceof Reply)
24
+ t.assert.strictEqual(callOrder++, 2)
25
+ t.assert.strictEqual(msg, firstEncounteredMessage)
26
+ })
27
+
28
+ diagnostics.subscribe('tracing:fastify.request.handler:error', (msg) => {
29
+ t.assert.ok(msg.request instanceof Request)
30
+ t.assert.ok(msg.reply instanceof Reply)
31
+ t.assert.ok(msg.error instanceof Error)
32
+ t.assert.strictEqual(callOrder++, 1)
33
+ t.assert.strictEqual(msg.error.message, 'borked')
34
+ })
35
+
36
+ const fastify = Fastify()
37
+ fastify.route({
38
+ method: 'GET',
39
+ url: '/',
40
+ handler: function (req, reply) {
41
+ throw new Error('borked')
42
+ }
43
+ })
44
+
45
+ const fastifyServer = await fastify.listen({ port: 0 })
46
+ t.after(() => { fastify.close() })
47
+
48
+ const response = await fetch(fastifyServer, {
49
+ method: 'GET'
50
+ })
51
+ t.assert.ok(!response.ok)
52
+ t.assert.strictEqual(response.status, 500)
53
+ })