fastify 5.0.0-alpha.2 → 5.0.0-alpha.4

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 (290) hide show
  1. package/README.md +2 -2
  2. package/SPONSORS.md +2 -0
  3. package/build/build-validation.js +3 -15
  4. package/docs/Guides/Ecosystem.md +4 -0
  5. package/docs/Guides/Getting-Started.md +0 -2
  6. package/docs/Guides/Migration-Guide-V4.md +48 -0
  7. package/docs/Guides/Recommendations.md +8 -6
  8. package/docs/Reference/Errors.md +0 -2
  9. package/docs/Reference/Hooks.md +5 -9
  10. package/docs/Reference/Logging.md +1 -1
  11. package/docs/Reference/Reply.md +9 -11
  12. package/docs/Reference/Request.md +0 -11
  13. package/docs/Reference/Routes.md +4 -23
  14. package/docs/Reference/Server.md +30 -40
  15. package/docs/Reference/Type-Providers.md +2 -2
  16. package/docs/Reference/TypeScript.md +16 -18
  17. package/docs/Reference/Validation-and-Serialization.md +62 -27
  18. package/docs/Reference/Warnings.md +0 -26
  19. package/eslint.config.js +9 -25
  20. package/fastify.d.ts +10 -23
  21. package/fastify.js +60 -61
  22. package/lib/configValidator.js +130 -182
  23. package/lib/context.js +1 -22
  24. package/lib/decorate.js +2 -2
  25. package/lib/errors.js +0 -6
  26. package/lib/handleRequest.js +5 -5
  27. package/lib/reply.js +34 -74
  28. package/lib/request.js +0 -45
  29. package/lib/route.js +12 -27
  30. package/lib/schemas.js +27 -22
  31. package/lib/server.js +6 -11
  32. package/lib/symbols.js +1 -1
  33. package/lib/validation.js +27 -6
  34. package/lib/warnings.js +1 -92
  35. package/lib/wrapThenable.js +1 -1
  36. package/package.json +14 -15
  37. package/test/decorator.test.js +1 -1
  38. package/test/diagnostics-channel/404.test.js +1 -1
  39. package/test/diagnostics-channel/async-delay-request.test.js +1 -1
  40. package/test/diagnostics-channel/async-request.test.js +1 -1
  41. package/test/diagnostics-channel/error-before-handler.test.js +1 -1
  42. package/test/diagnostics-channel/error-request.test.js +1 -1
  43. package/test/diagnostics-channel/error-status.test.js +1 -1
  44. package/test/diagnostics-channel/init.test.js +2 -2
  45. package/test/diagnostics-channel/sync-delay-request.test.js +1 -1
  46. package/test/diagnostics-channel/sync-request-reply.test.js +1 -1
  47. package/test/diagnostics-channel/sync-request.test.js +1 -1
  48. package/test/{copy.test.js → http-methods/copy.test.js} +2 -1
  49. package/test/http-methods/custom-http-methods.test.js +111 -0
  50. package/test/{get.test.js → http-methods/get.test.js} +1 -1
  51. package/test/{head.test.js → http-methods/head.test.js} +7 -87
  52. package/test/{lock.test.js → http-methods/lock.test.js} +2 -1
  53. package/test/{mkcalendar.test.js → http-methods/mkcalendar.test.js} +2 -1
  54. package/test/{mkcol.test.js → http-methods/mkcol.test.js} +2 -1
  55. package/test/{move.test.js → http-methods/move.test.js} +2 -1
  56. package/test/{propfind.test.js → http-methods/propfind.test.js} +2 -1
  57. package/test/{proppatch.test.js → http-methods/proppatch.test.js} +2 -1
  58. package/test/{report.test.js → http-methods/report.test.js} +2 -1
  59. package/test/{search.test.js → http-methods/search.test.js} +2 -1
  60. package/test/{trace.test.js → http-methods/trace.test.js} +2 -1
  61. package/test/{unlock.test.js → http-methods/unlock.test.js} +2 -1
  62. package/test/internals/all.test.js +3 -3
  63. package/test/internals/decorator.test.js +2 -2
  64. package/test/internals/errors.test.js +7 -17
  65. package/test/internals/initialConfig.test.js +0 -31
  66. package/test/internals/reply-serialize.test.js +25 -10
  67. package/test/internals/reply.test.js +31 -153
  68. package/test/internals/request-validate.test.js +21 -12
  69. package/test/internals/request.test.js +1 -18
  70. package/test/internals/validation.test.js +49 -56
  71. package/test/listen.1.test.js +66 -14
  72. package/test/listen.5.test.js +11 -0
  73. package/test/reply-trailers.test.js +1 -32
  74. package/test/route-shorthand.test.js +3 -1
  75. package/test/route.3.test.js +4 -1
  76. package/test/route.7.test.js +2 -12
  77. package/test/route.8.test.js +34 -5
  78. package/test/router-options.test.js +6 -3
  79. package/test/schema-examples.test.js +15 -6
  80. package/test/schema-feature.test.js +178 -35
  81. package/test/schema-serialization.test.js +125 -21
  82. package/test/schema-validation.test.js +154 -3
  83. package/test/skip-reply-send.test.js +6 -6
  84. package/test/stream-serializers.test.js +37 -0
  85. package/test/throw.test.js +2 -14
  86. package/test/types/errors.test-d.ts +1 -2
  87. package/test/types/fastify.test-d.ts +23 -34
  88. package/test/types/hooks.test-d.ts +56 -56
  89. package/test/types/instance.test-d.ts +3 -3
  90. package/test/types/reply.test-d.ts +7 -8
  91. package/test/types/request.test-d.ts +2 -12
  92. package/test/types/route.test-d.ts +158 -158
  93. package/test/types/schema.test-d.ts +22 -5
  94. package/test/versioned-routes.test.js +0 -90
  95. package/test/web-api.test.js +75 -0
  96. package/types/errors.d.ts +78 -79
  97. package/types/hooks.d.ts +18 -18
  98. package/types/instance.d.ts +1 -1
  99. package/types/logger.d.ts +7 -7
  100. package/types/reply.d.ts +18 -22
  101. package/types/request.d.ts +8 -14
  102. package/types/route.d.ts +5 -6
  103. package/types/type-provider.d.ts +1 -1
  104. package/.tap/processinfo/09002e93-10ad-430c-bc86-c0576928b0ed.json +0 -241
  105. package/.tap/processinfo/ee66c5ab-635d-48b5-8be6-3dc3ceea5bfc.json +0 -268
  106. package/.tap/test-results/test/404s.test.js.tap +0 -623
  107. package/.tap/test-results/test/500s.test.js.tap +0 -64
  108. package/.tap/test-results/test/allowUnsafeRegex.test.js.tap +0 -36
  109. package/.tap/test-results/test/als.test.js.tap +0 -15
  110. package/.tap/test-results/test/async-await.test.js.tap +0 -184
  111. package/.tap/test-results/test/async-dispose.test.js.tap +0 -8
  112. package/.tap/test-results/test/async_hooks.test.js.tap +0 -10
  113. package/.tap/test-results/test/bodyLimit.test.js.tap +0 -48
  114. package/.tap/test-results/test/buffer.test.js.tap +0 -20
  115. package/.tap/test-results/test/build/error-serializer.test.js.tap +0 -12
  116. package/.tap/test-results/test/build/version.test.js.tap +0 -7
  117. package/.tap/test-results/test/case-insensitive.test.js.tap +0 -36
  118. package/.tap/test-results/test/chainable.test.js.tap +0 -17
  119. package/.tap/test-results/test/check.test.js.tap +0 -10
  120. package/.tap/test-results/test/childLoggerFactory.test.js.tap +0 -23
  121. package/.tap/test-results/test/client-timeout.test.js.tap +0 -7
  122. package/.tap/test-results/test/close-pipelining.test.js.tap +0 -15
  123. package/.tap/test-results/test/close.test.js.tap +0 -172
  124. package/.tap/test-results/test/connectionTimeout.test.js.tap +0 -12
  125. package/.tap/test-results/test/constrained-routes.test.js.tap +0 -173
  126. package/.tap/test-results/test/content-length.test.js.tap +0 -46
  127. package/.tap/test-results/test/content-parser.test.js.tap +0 -266
  128. package/.tap/test-results/test/content-type.test.js.tap +0 -14
  129. package/.tap/test-results/test/context-config.test.js.tap +0 -41
  130. package/.tap/test-results/test/copy.test.js.tap +0 -14
  131. package/.tap/test-results/test/custom-http-server.test.js.tap +0 -30
  132. package/.tap/test-results/test/custom-parser-async.test.js.tap +0 -21
  133. package/.tap/test-results/test/custom-parser.0.test.js.tap +0 -199
  134. package/.tap/test-results/test/custom-parser.1.test.js.tap +0 -90
  135. package/.tap/test-results/test/custom-parser.2.test.js.tap +0 -22
  136. package/.tap/test-results/test/custom-parser.3.test.js.tap +0 -53
  137. package/.tap/test-results/test/custom-parser.4.test.js.tap +0 -45
  138. package/.tap/test-results/test/custom-parser.5.test.js.tap +0 -41
  139. package/.tap/test-results/test/custom-querystring-parser.test.js.tap +0 -46
  140. package/.tap/test-results/test/decorator.test.js.tap +0 -465
  141. package/.tap/test-results/test/delete.test.js.tap +0 -110
  142. package/.tap/test-results/test/diagnostics-channel/404.test.js.tap +0 -15
  143. package/.tap/test-results/test/diagnostics-channel/async-delay-request.test.js.tap +0 -25
  144. package/.tap/test-results/test/diagnostics-channel/async-request.test.js.tap +0 -24
  145. package/.tap/test-results/test/diagnostics-channel/error-before-handler.test.js.tap +0 -9
  146. package/.tap/test-results/test/diagnostics-channel/error-request.test.js.tap +0 -20
  147. package/.tap/test-results/test/diagnostics-channel/error-status.test.js.tap +0 -10
  148. package/.tap/test-results/test/diagnostics-channel/init.test.js.tap +0 -14
  149. package/.tap/test-results/test/diagnostics-channel/sync-delay-request.test.js.tap +0 -16
  150. package/.tap/test-results/test/diagnostics-channel/sync-request-reply.test.js.tap +0 -16
  151. package/.tap/test-results/test/diagnostics-channel/sync-request.test.js.tap +0 -19
  152. package/.tap/test-results/test/encapsulated-child-logger-factory.test.js.tap +0 -18
  153. package/.tap/test-results/test/encapsulated-error-handler.test.js.tap +0 -243
  154. package/.tap/test-results/test/esm/errorCodes.test.mjs.tap +0 -9
  155. package/.tap/test-results/test/esm/esm.test.mjs.tap +0 -8
  156. package/.tap/test-results/test/esm/index.test.js.tap +0 -8
  157. package/.tap/test-results/test/fastify-instance.test.js.tap +0 -114
  158. package/.tap/test-results/test/findRoute.test.js.tap +0 -37
  159. package/.tap/test-results/test/fluent-schema.test.js.tap +0 -36
  160. package/.tap/test-results/test/genReqId.test.js.tap +0 -106
  161. package/.tap/test-results/test/get.test.js.tap +0 -151
  162. package/.tap/test-results/test/handler-context.test.js.tap +0 -19
  163. package/.tap/test-results/test/has-route.test.js.tap +0 -30
  164. package/.tap/test-results/test/head.test.js.tap +0 -130
  165. package/.tap/test-results/test/header-overflow.test.js.tap +0 -16
  166. package/.tap/test-results/test/hooks-async.test.js.tap +0 -286
  167. package/.tap/test-results/test/hooks.on-listen.test.js.tap +0 -311
  168. package/.tap/test-results/test/hooks.on-ready.test.js.tap +0 -151
  169. package/.tap/test-results/test/hooks.test.js.tap +0 -966
  170. package/.tap/test-results/test/http2/closing.test.js.tap +0 -35
  171. package/.tap/test-results/test/http2/constraint.test.js.tap +0 -32
  172. package/.tap/test-results/test/http2/head.test.js.tap +0 -9
  173. package/.tap/test-results/test/http2/missing-http2-module.test.js.tap +0 -8
  174. package/.tap/test-results/test/http2/plain.test.js.tap +0 -22
  175. package/.tap/test-results/test/http2/secure-with-fallback.test.js.tap +0 -40
  176. package/.tap/test-results/test/http2/secure.test.js.tap +0 -27
  177. package/.tap/test-results/test/http2/unknown-http-method.test.js.tap +0 -9
  178. package/.tap/test-results/test/https/custom-https-server.test.js.tap +0 -10
  179. package/.tap/test-results/test/https/https.test.js.tap +0 -45
  180. package/.tap/test-results/test/imports.test.js.tap +0 -14
  181. package/.tap/test-results/test/inject.test.js.tap +0 -165
  182. package/.tap/test-results/test/internals/all.test.js.tap +0 -42
  183. package/.tap/test-results/test/internals/contentTypeParser.test.js.tap +0 -14
  184. package/.tap/test-results/test/internals/context.test.js.tap +0 -14
  185. package/.tap/test-results/test/internals/decorator.test.js.tap +0 -51
  186. package/.tap/test-results/test/internals/errors.test.js.tap +0 -1212
  187. package/.tap/test-results/test/internals/handleRequest.test.js.tap +0 -69
  188. package/.tap/test-results/test/internals/hookRunner.test.js.tap +0 -143
  189. package/.tap/test-results/test/internals/hooks.test.js.tap +0 -45
  190. package/.tap/test-results/test/internals/initialConfig.test.js.tap +0 -125
  191. package/.tap/test-results/test/internals/logger.test.js.tap +0 -71
  192. package/.tap/test-results/test/internals/plugin.test.js.tap +0 -48
  193. package/.tap/test-results/test/internals/reply-serialize.test.js.tap +0 -166
  194. package/.tap/test-results/test/internals/reply.test.js.tap +0 -688
  195. package/.tap/test-results/test/internals/reqIdGenFactory.test.js.tap +0 -74
  196. package/.tap/test-results/test/internals/request-validate.test.js.tap +0 -384
  197. package/.tap/test-results/test/internals/request.test.js.tap +0 -163
  198. package/.tap/test-results/test/internals/server.test.js.tap +0 -30
  199. package/.tap/test-results/test/internals/validation.test.js.tap +0 -121
  200. package/.tap/test-results/test/keepAliveTimeout.test.js.tap +0 -12
  201. package/.tap/test-results/test/listen.1.test.js.tap +0 -31
  202. package/.tap/test-results/test/listen.2.test.js.tap +0 -46
  203. package/.tap/test-results/test/listen.3.test.js.tap +0 -25
  204. package/.tap/test-results/test/listen.4.test.js.tap +0 -51
  205. package/.tap/test-results/test/lock.test.js.tap +0 -29
  206. package/.tap/test-results/test/logger/instantiation.test.js.tap +0 -92
  207. package/.tap/test-results/test/logger/logging.test.js.tap +0 -117
  208. package/.tap/test-results/test/logger/options.test.js.tap +0 -165
  209. package/.tap/test-results/test/logger/request.test.js.tap +0 -82
  210. package/.tap/test-results/test/logger/response.test.js.tap +0 -38
  211. package/.tap/test-results/test/maxRequestsPerSocket.test.js.tap +0 -44
  212. package/.tap/test-results/test/method-missing.test.js.tap +0 -8
  213. package/.tap/test-results/test/middleware.test.js.tap +0 -17
  214. package/.tap/test-results/test/mkcalendar.test.js.tap +0 -43
  215. package/.tap/test-results/test/mkcol.test.js.tap +0 -14
  216. package/.tap/test-results/test/move.test.js.tap +0 -15
  217. package/.tap/test-results/test/noop-set.test.js.tap +0 -8
  218. package/.tap/test-results/test/nullable-validation.test.js.tap +0 -36
  219. package/.tap/test-results/test/options.error-handler.test.js.tap +0 -186
  220. package/.tap/test-results/test/options.test.js.tap +0 -174
  221. package/.tap/test-results/test/output-validation.test.js.tap +0 -66
  222. package/.tap/test-results/test/patch.error-handler.test.js.tap +0 -206
  223. package/.tap/test-results/test/patch.test.js.tap +0 -182
  224. package/.tap/test-results/test/plugin.1.test.js.tap +0 -78
  225. package/.tap/test-results/test/plugin.2.test.js.tap +0 -102
  226. package/.tap/test-results/test/plugin.3.test.js.tap +0 -58
  227. package/.tap/test-results/test/plugin.4.test.js.tap +0 -164
  228. package/.tap/test-results/test/post-empty-body.test.js.tap +0 -8
  229. package/.tap/test-results/test/pretty-print.test.js.tap +0 -82
  230. package/.tap/test-results/test/promises.test.js.tap +0 -46
  231. package/.tap/test-results/test/propfind.test.js.tap +0 -43
  232. package/.tap/test-results/test/proppatch.test.js.tap +0 -29
  233. package/.tap/test-results/test/proto-poisoning.test.js.tap +0 -47
  234. package/.tap/test-results/test/put.error-handler.test.js.tap +0 -206
  235. package/.tap/test-results/test/put.test.js.tap +0 -182
  236. package/.tap/test-results/test/register.test.js.tap +0 -61
  237. package/.tap/test-results/test/reply-code.test.js.tap +0 -40
  238. package/.tap/test-results/test/reply-earlyHints.test.js.tap +0 -22
  239. package/.tap/test-results/test/reply-error.test.js.tap +0 -643
  240. package/.tap/test-results/test/reply-trailers.test.js.tap +0 -176
  241. package/.tap/test-results/test/report.test.js.tap +0 -43
  242. package/.tap/test-results/test/request-error.test.js.tap +0 -98
  243. package/.tap/test-results/test/request-id.test.js.tap +0 -38
  244. package/.tap/test-results/test/request.deprecated.test.js.tap +0 -13
  245. package/.tap/test-results/test/requestTimeout.test.js.tap +0 -21
  246. package/.tap/test-results/test/route-hooks.test.js.tap +0 -498
  247. package/.tap/test-results/test/route-prefix.test.js.tap +0 -195
  248. package/.tap/test-results/test/route-shorthand.test.js.tap +0 -190
  249. package/.tap/test-results/test/route.1.test.js.tap +0 -93
  250. package/.tap/test-results/test/route.2.test.js.tap +0 -28
  251. package/.tap/test-results/test/route.3.test.js.tap +0 -39
  252. package/.tap/test-results/test/route.4.test.js.tap +0 -32
  253. package/.tap/test-results/test/route.5.test.js.tap +0 -54
  254. package/.tap/test-results/test/route.6.test.js.tap +0 -81
  255. package/.tap/test-results/test/route.7.test.js.tap +0 -93
  256. package/.tap/test-results/test/route.8.test.js.tap +0 -38
  257. package/.tap/test-results/test/router-options.test.js.tap +0 -104
  258. package/.tap/test-results/test/same-shape.test.js.tap +0 -22
  259. package/.tap/test-results/test/schema-examples.test.js.tap +0 -85
  260. package/.tap/test-results/test/schema-feature.test.js.tap +0 -445
  261. package/.tap/test-results/test/schema-serialization.test.js.tap +0 -194
  262. package/.tap/test-results/test/schema-special-usage.test.js.tap +0 -186
  263. package/.tap/test-results/test/schema-validation.test.js.tap +0 -199
  264. package/.tap/test-results/test/search.test.js.tap +0 -77
  265. package/.tap/test-results/test/serialize-response.test.js.tap +0 -26
  266. package/.tap/test-results/test/server.test.js.tap +0 -65
  267. package/.tap/test-results/test/set-error-handler.test.js.tap +0 -7
  268. package/.tap/test-results/test/skip-reply-send.test.js.tap +0 -272
  269. package/.tap/test-results/test/stream.1.test.js.tap +0 -36
  270. package/.tap/test-results/test/stream.2.test.js.tap +0 -20
  271. package/.tap/test-results/test/stream.3.test.js.tap +0 -34
  272. package/.tap/test-results/test/stream.4.test.js.tap +0 -40
  273. package/.tap/test-results/test/stream.5.test.js.tap +0 -37
  274. package/.tap/test-results/test/sync-routes.test.js.tap +0 -19
  275. package/.tap/test-results/test/throw.test.js.tap +0 -116
  276. package/.tap/test-results/test/trace.test.js.tap +0 -7
  277. package/.tap/test-results/test/trust-proxy.test.js.tap +0 -109
  278. package/.tap/test-results/test/type-provider.test.js.tap +0 -12
  279. package/.tap/test-results/test/unlock.test.js.tap +0 -14
  280. package/.tap/test-results/test/upgrade.test.js.tap +0 -8
  281. package/.tap/test-results/test/url-rewriting.test.js.tap +0 -39
  282. package/.tap/test-results/test/useSemicolonDelimiter.test.js.tap +0 -33
  283. package/.tap/test-results/test/validation-error-handling.test.js.tap +0 -180
  284. package/.tap/test-results/test/versioned-routes.test.js.tap +0 -151
  285. package/.tap/test-results/test/web-api.test.js.tap +0 -51
  286. package/.tap/test-results/test/wrapThenable.test.js.tap +0 -11
  287. package/EXPENSE_POLICY.md +0 -105
  288. package/lib/httpMethods.js +0 -40
  289. package/test/method-missing.test.js +0 -24
  290. package/test/request.deprecated.test.js +0 -38
@@ -5,7 +5,6 @@ const { test } = require('tap')
5
5
  const Request = require('../../lib/request')
6
6
  const Context = require('../../lib/context')
7
7
  const {
8
- kPublicRouteContext,
9
8
  kReply,
10
9
  kRequest,
11
10
  kOptions
@@ -67,15 +66,9 @@ test('Regular request', t => {
67
66
  t.equal(request.originalUrl, '/')
68
67
  t.equal(request.socket, req.socket)
69
68
  t.equal(request.protocol, 'http')
70
- t.equal(request.routerPath, context.config.url)
71
- t.equal(request.routerMethod, context.config.method)
72
- t.equal(request.routeConfig, context[kPublicRouteContext].config)
73
- t.equal(request.routeSchema, context[kPublicRouteContext].schema)
74
69
  // Aim to not bad property keys (including Symbols)
75
70
  t.notOk('undefined' in request)
76
71
 
77
- // This will be removed, it's deprecated
78
- t.equal(request.connection, req.connection)
79
72
  t.end()
80
73
  })
81
74
 
@@ -128,16 +121,10 @@ test('Request with undefined config', t => {
128
121
  t.equal(request.originalUrl, '/')
129
122
  t.equal(request.socket, req.socket)
130
123
  t.equal(request.protocol, 'http')
131
- t.equal(request.routeSchema, context[kPublicRouteContext].schema)
132
- t.equal(request.routerPath, undefined)
133
- t.equal(request.routerMethod, undefined)
134
- t.equal(request.routeConfig, undefined)
135
124
 
136
125
  // Aim to not bad property keys (including Symbols)
137
126
  t.notOk('undefined' in request)
138
127
 
139
- // This will be removed, it's deprecated
140
- t.equal(request.connection, req.connection)
141
128
  t.end()
142
129
  })
143
130
 
@@ -178,7 +165,7 @@ test('Regular request - host header has precedence over authority', t => {
178
165
  })
179
166
 
180
167
  test('Request with trust proxy', t => {
181
- t.plan(22)
168
+ t.plan(18)
182
169
  const headers = {
183
170
  'x-forwarded-for': '2.2.2.2, 1.1.1.1',
184
171
  'x-forwarded-host': 'example.com'
@@ -233,10 +220,6 @@ test('Request with trust proxy', t => {
233
220
  t.type(request.validateInput, Function)
234
221
  t.type(request.getValidationFunction, Function)
235
222
  t.type(request.compileValidationSchema, Function)
236
- t.equal(request.routerPath, context.config.url)
237
- t.equal(request.routerMethod, context.config.method)
238
- t.equal(request.routeConfig, context[kPublicRouteContext].config)
239
- t.equal(request.routeSchema, context[kPublicRouteContext].schema)
240
223
  })
241
224
 
242
225
  test('Request with trust proxy, encrypted', t => {
@@ -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 - payload schema', t => {
66
+ test('build schema - body schema', t => {
67
67
  t.plan(1)
68
68
  const opts = {
69
69
  schema: {
@@ -79,11 +79,35 @@ 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
- const serverConfig = {
85
- jsonShorthand: true
86
- }
110
+ const serverConfig = {}
87
111
  const opts = {
88
112
  schema: {
89
113
  query: {
@@ -102,9 +126,7 @@ test('build schema - avoid repeated normalize schema', t => {
102
126
 
103
127
  test('build schema - query schema', t => {
104
128
  t.plan(2)
105
- const serverConfig = {
106
- jsonShorthand: true
107
- }
129
+ const serverConfig = {}
108
130
  const opts = {
109
131
  schema: {
110
132
  query: {
@@ -123,13 +145,14 @@ test('build schema - query schema', t => {
123
145
 
124
146
  test('build schema - query schema abbreviated', t => {
125
147
  t.plan(2)
126
- const serverConfig = {
127
- jsonShorthand: true
128
- }
148
+ const serverConfig = {}
129
149
  const opts = {
130
150
  schema: {
131
151
  query: {
132
- hello: { type: 'string' }
152
+ type: 'object',
153
+ properties: {
154
+ hello: { type: 'string' }
155
+ }
133
156
  }
134
157
  }
135
158
  }
@@ -158,13 +181,14 @@ test('build schema - querystring schema', t => {
158
181
 
159
182
  test('build schema - querystring schema abbreviated', t => {
160
183
  t.plan(2)
161
- const serverConfig = {
162
- jsonShorthand: true
163
- }
184
+ const serverConfig = {}
164
185
  const opts = {
165
186
  schema: {
166
187
  querystring: {
167
- hello: { type: 'string' }
188
+ type: 'object',
189
+ properties: {
190
+ hello: { type: 'string' }
191
+ }
168
192
  }
169
193
  }
170
194
  }
@@ -177,9 +201,7 @@ test('build schema - querystring schema abbreviated', t => {
177
201
  test('build schema - must throw if querystring and query schema exist', t => {
178
202
  t.plan(2)
179
203
  try {
180
- const serverConfig = {
181
- jsonShorthand: true
182
- }
204
+ const serverConfig = {}
183
205
  const opts = {
184
206
  schema: {
185
207
  query: {
@@ -249,14 +271,14 @@ test('build schema - headers are lowercase', t => {
249
271
  }
250
272
  validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
251
273
  t.ok(schema.properties['content-type'], 'lowercase content-type exists')
252
- return () => {}
274
+ return () => { }
253
275
  })
254
276
  })
255
277
 
256
278
  test('build schema - headers are not lowercased in case of custom object', t => {
257
279
  t.plan(1)
258
280
 
259
- class Headers {}
281
+ class Headers { }
260
282
  const opts = {
261
283
  schema: {
262
284
  headers: new Headers()
@@ -264,14 +286,14 @@ test('build schema - headers are not lowercased in case of custom object', t =>
264
286
  }
265
287
  validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
266
288
  t.type(schema, Headers)
267
- return () => {}
289
+ return () => { }
268
290
  })
269
291
  })
270
292
 
271
293
  test('build schema - headers are not lowercased in case of custom validator provided', t => {
272
294
  t.plan(1)
273
295
 
274
- class Headers {}
296
+ class Headers { }
275
297
  const opts = {
276
298
  schema: {
277
299
  headers: new Headers()
@@ -279,7 +301,7 @@ test('build schema - headers are not lowercased in case of custom validator prov
279
301
  }
280
302
  validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
281
303
  t.type(schema, Headers)
282
- return () => {}
304
+ return () => { }
283
305
  }, true)
284
306
  })
285
307
 
@@ -297,21 +319,14 @@ test('build schema - uppercased headers are not included', t => {
297
319
  }
298
320
  validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => {
299
321
  t.notOk('Content-Type' in schema.properties, 'uppercase does not exist')
300
- return () => {}
322
+ return () => { }
301
323
  })
302
324
  })
303
325
 
304
326
  test('build schema - mixed schema types are individually skipped or normalized', t => {
305
- t.plan(6)
327
+ t.plan(2)
306
328
 
307
- class CustomSchemaClass {}
308
- const nonNormalizedSchema = {
309
- hello: { type: 'string' }
310
- }
311
- const normalizedSchema = {
312
- type: 'object',
313
- properties: nonNormalizedSchema
314
- }
329
+ class CustomSchemaClass { }
315
330
 
316
331
  const testCases = [{
317
332
  schema: {
@@ -329,32 +344,10 @@ test('build schema - mixed schema types are individually skipped or normalized',
329
344
  assertions: (schema) => {
330
345
  t.type(schema.response[200], CustomSchemaClass)
331
346
  }
332
- }, {
333
- schema: {
334
- body: nonNormalizedSchema,
335
- response: {
336
- 200: new CustomSchemaClass()
337
- }
338
- },
339
- assertions: (schema) => {
340
- t.same(schema.body, normalizedSchema)
341
- t.type(schema.response[200], CustomSchemaClass)
342
- }
343
- }, {
344
- schema: {
345
- body: new CustomSchemaClass(),
346
- response: {
347
- 200: nonNormalizedSchema
348
- }
349
- },
350
- assertions: (schema) => {
351
- t.type(schema.body, CustomSchemaClass)
352
- t.same(schema.response[200], normalizedSchema)
353
- }
354
347
  }]
355
348
 
356
349
  testCases.forEach((testCase) => {
357
- const result = normalizeSchema(testCase.schema, { jsonShorthand: true })
350
+ const result = normalizeSchema(testCase.schema, {})
358
351
  testCase.assertions(result)
359
352
  })
360
353
  })
@@ -12,12 +12,16 @@ before(async function () {
12
12
  })
13
13
 
14
14
  test('listen works without arguments', async t => {
15
- process.on('warning', () => {
15
+ const doNotWarn = () => {
16
16
  t.fail('should not be deprecated')
17
- })
17
+ }
18
+ process.on('warning', doNotWarn)
18
19
 
19
20
  const fastify = Fastify()
20
- t.teardown(fastify.close.bind(fastify))
21
+ t.teardown(() => {
22
+ fastify.close()
23
+ process.removeListener('warning', doNotWarn)
24
+ })
21
25
  await fastify.listen()
22
26
  const address = fastify.server.address()
23
27
  t.equal(address.address, localhost)
@@ -25,12 +29,16 @@ test('listen works without arguments', async t => {
25
29
  })
26
30
 
27
31
  test('Async/await listen with arguments', async t => {
28
- process.on('warning', () => {
32
+ const doNotWarn = () => {
29
33
  t.fail('should not be deprecated')
30
- })
34
+ }
35
+ process.on('warning', doNotWarn)
31
36
 
32
37
  const fastify = Fastify()
33
- t.teardown(fastify.close.bind(fastify))
38
+ t.teardown(() => {
39
+ fastify.close()
40
+ process.removeListener('warning', doNotWarn)
41
+ })
34
42
  const addr = await fastify.listen({ port: 0, host: '0.0.0.0' })
35
43
  const address = fastify.server.address()
36
44
  t.equal(addr, `http://127.0.0.1:${address.port}`)
@@ -42,13 +50,17 @@ test('Async/await listen with arguments', async t => {
42
50
  })
43
51
 
44
52
  test('listen accepts a callback', t => {
45
- process.on('warning', () => {
53
+ t.plan(2)
54
+ const doNotWarn = () => {
46
55
  t.fail('should not be deprecated')
47
- })
56
+ }
57
+ process.on('warning', doNotWarn)
48
58
 
49
- t.plan(2)
50
59
  const fastify = Fastify()
51
- t.teardown(fastify.close.bind(fastify))
60
+ t.teardown(() => {
61
+ fastify.close()
62
+ process.removeListener('warning', doNotWarn)
63
+ })
52
64
  fastify.listen({ port: 0 }, (err) => {
53
65
  t.equal(fastify.server.address().address, localhost)
54
66
  t.error(err)
@@ -56,13 +68,17 @@ test('listen accepts a callback', t => {
56
68
  })
57
69
 
58
70
  test('listen accepts options and a callback', t => {
59
- process.on('warning', () => {
71
+ t.plan(1)
72
+ const doNotWarn = () => {
60
73
  t.fail('should not be deprecated')
61
- })
74
+ }
75
+ process.on('warning', doNotWarn)
62
76
 
63
- t.plan(1)
64
77
  const fastify = Fastify()
65
- t.teardown(fastify.close.bind(fastify))
78
+ t.teardown(() => {
79
+ fastify.close()
80
+ process.removeListener('warning', doNotWarn)
81
+ })
66
82
  fastify.listen({
67
83
  port: 0,
68
84
  host: 'localhost',
@@ -89,3 +105,39 @@ test('listen after Promise.resolve()', t => {
89
105
  })
90
106
  })
91
107
  })
108
+
109
+ test('listen works with undefined host', async t => {
110
+ const doNotWarn = () => {
111
+ t.fail('should not be deprecated')
112
+ }
113
+ process.on('warning', doNotWarn)
114
+
115
+ const fastify = Fastify()
116
+ t.teardown(fastify.close.bind(fastify))
117
+ t.teardown(() => {
118
+ fastify.close()
119
+ process.removeListener('warning', doNotWarn)
120
+ })
121
+ await fastify.listen({ host: undefined, port: 0 })
122
+ const address = fastify.server.address()
123
+ t.equal(address.address, localhost)
124
+ t.ok(address.port > 0)
125
+ })
126
+
127
+ test('listen works with null host', async t => {
128
+ const doNotWarn = () => {
129
+ t.fail('should not be deprecated')
130
+ }
131
+ process.on('warning', doNotWarn)
132
+
133
+ const fastify = Fastify()
134
+ t.teardown(fastify.close.bind(fastify))
135
+ t.teardown(() => {
136
+ fastify.close()
137
+ process.removeListener('warning', doNotWarn)
138
+ })
139
+ await fastify.listen({ host: null, port: 0 })
140
+ const address = fastify.server.address()
141
+ t.equal(address.address, localhost)
142
+ t.ok(address.port > 0)
143
+ })
@@ -5,6 +5,14 @@ const net = require('node:net')
5
5
  const Fastify = require('../fastify')
6
6
  const { once } = require('node:events')
7
7
 
8
+ function createDeferredPromise () {
9
+ const promise = {}
10
+ promise.promise = new Promise((resolve) => {
11
+ promise.resolve = resolve
12
+ })
13
+ return promise
14
+ }
15
+
8
16
  test('same port conflict and success should not fire callback multiple times - callback', async (t) => {
9
17
  t.plan(7)
10
18
  const server = net.createServer()
@@ -13,6 +21,7 @@ test('same port conflict and success should not fire callback multiple times - c
13
21
  const option = { port: server.address().port, host: server.address().address }
14
22
  let count = 0
15
23
  const fastify = Fastify()
24
+ const promise = createDeferredPromise()
16
25
  function callback (err) {
17
26
  switch (count) {
18
27
  case 6: {
@@ -20,6 +29,7 @@ test('same port conflict and success should not fire callback multiple times - c
20
29
  t.error(err)
21
30
  fastify.close((err) => {
22
31
  t.error(err)
32
+ promise.resolve()
23
33
  })
24
34
  break
25
35
  }
@@ -41,6 +51,7 @@ test('same port conflict and success should not fire callback multiple times - c
41
51
  count++
42
52
  }
43
53
  fastify.listen(option, callback)
54
+ await promise.promise
44
55
  })
45
56
 
46
57
  test('same port conflict and success should not fire callback multiple times - promise', async (t) => {
@@ -186,37 +186,6 @@ test('error in trailers should be ignored', t => {
186
186
  })
187
187
  })
188
188
 
189
- test('should emit deprecation warning when using direct return', t => {
190
- t.plan(7)
191
-
192
- const fastify = Fastify()
193
-
194
- fastify.get('/', function (request, reply) {
195
- reply.trailer('ETag', function (reply, payload) {
196
- return 'custom-etag'
197
- })
198
- reply.send('')
199
- })
200
-
201
- process.on('warning', onWarning)
202
- function onWarning (warning) {
203
- t.equal(warning.name, 'DeprecationWarning')
204
- t.equal(warning.code, 'FSTDEP013')
205
- }
206
- t.teardown(() => process.removeListener('warning', onWarning))
207
-
208
- fastify.inject({
209
- method: 'GET',
210
- url: '/'
211
- }, (error, res) => {
212
- t.error(error)
213
- t.equal(res.statusCode, 200)
214
- t.equal(res.headers.trailer, 'etag')
215
- t.equal(res.trailers.etag, 'custom-etag')
216
- t.notHas(res.headers, 'content-length')
217
- })
218
- })
219
-
220
189
  test('trailer handler counter', t => {
221
190
  t.plan(2)
222
191
 
@@ -412,7 +381,7 @@ test('throw error when trailer header name is not allowed', t => {
412
381
  fastify.get('/', function (request, reply) {
413
382
  for (const key of INVALID_TRAILERS) {
414
383
  try {
415
- reply.trailer(key, () => {})
384
+ reply.trailer(key, () => { })
416
385
  } catch (err) {
417
386
  t.equal(err.message, `Called reply.trailer with an invalid header name: ${key}`)
418
387
  }
@@ -4,9 +4,11 @@ const t = require('tap')
4
4
  const test = t.test
5
5
  const sget = require('simple-get').concat
6
6
  const Fastify = require('../fastify')
7
- const supportedMethods = require('../lib/httpMethods').supportedMethods
8
7
 
9
8
  test('route-shorthand', t => {
9
+ const methodsReader = new Fastify()
10
+ const supportedMethods = methodsReader.supportedMethods
11
+
10
12
  t.plan(supportedMethods.length + 1)
11
13
  const test = t.test
12
14
 
@@ -54,7 +54,10 @@ test('multiple routes with one schema', t => {
54
54
 
55
55
  const schema = {
56
56
  query: {
57
- id: { type: 'number' }
57
+ type: 'object',
58
+ properties: {
59
+ id: { type: 'number' }
60
+ }
58
61
  }
59
62
  }
60
63
 
@@ -5,7 +5,6 @@ const split = require('split2')
5
5
  const t = require('tap')
6
6
  const test = t.test
7
7
  const Fastify = require('..')
8
- const proxyquire = require('proxyquire')
9
8
 
10
9
  test("HEAD route should handle stream.on('error')", t => {
11
10
  t.plan(6)
@@ -176,18 +175,9 @@ test('Set a custom HEAD route before GET one without disabling exposeHeadRoutes
176
175
  })
177
176
 
178
177
  test('Set a custom HEAD route before GET one without disabling exposeHeadRoutes (route)', t => {
179
- t.plan(7)
180
-
181
- function onWarning () {
182
- t.pass('warning emitted')
183
- }
178
+ t.plan(6)
184
179
 
185
- const route = proxyquire('../lib/route', {
186
- './warnings': {
187
- FSTDEP007: onWarning
188
- }
189
- })
190
- const fastify = proxyquire('..', { './lib/route.js': route })()
180
+ const fastify = Fastify()
191
181
 
192
182
  const resBuffer = Buffer.from('I am a coffee!')
193
183
 
@@ -4,10 +4,12 @@ const t = require('tap')
4
4
  const test = t.test
5
5
  const sget = require('simple-get').concat
6
6
  const Fastify = require('../fastify')
7
- const { FST_ERR_INVALID_URL } = require('../lib/errors')
7
+ const {
8
+ FST_ERR_INVALID_URL
9
+ } = require('../lib/errors')
8
10
  const { getServerUrl } = require('./helper')
9
11
 
10
- test('Request and Reply share the route config', async t => {
12
+ test('Request and Reply share the route options', async t => {
11
13
  t.plan(3)
12
14
 
13
15
  const fastify = Fastify()
@@ -22,9 +24,9 @@ test('Request and Reply share the route config', async t => {
22
24
  url: '/',
23
25
  config,
24
26
  handler: (req, reply) => {
25
- t.same(req.context, reply.context)
26
- t.same(req.context.config, reply.context.config)
27
- t.match(req.context.config, config, 'there are url and method additional properties')
27
+ t.same(req.routeOptions, reply.routeOptions)
28
+ t.same(req.routeOptions.config, reply.routeOptions.config)
29
+ t.match(req.routeOptions.config, config, 'there are url and method additional properties')
28
30
 
29
31
  reply.send({ hello: 'world' })
30
32
  }
@@ -140,3 +142,30 @@ test('using fastify.all when a catchall is defined does not degrade performance'
140
142
 
141
143
  t.pass()
142
144
  })
145
+
146
+ test('Adding manually HEAD route after GET with the same path throws Fastify duplicated route instance error', t => {
147
+ t.plan(1)
148
+
149
+ const fastify = Fastify()
150
+
151
+ fastify.route({
152
+ method: 'GET',
153
+ path: '/:param1',
154
+ handler: (req, reply) => {
155
+ reply.send({ hello: 'world' })
156
+ }
157
+ })
158
+
159
+ try {
160
+ fastify.route({
161
+ method: 'HEAD',
162
+ path: '/:param2',
163
+ handler: (req, reply) => {
164
+ reply.send({ hello: 'world' })
165
+ }
166
+ })
167
+ t.fail('Should throw fastify duplicated route declaration')
168
+ } catch (error) {
169
+ t.equal(error.code, 'FST_ERR_DUPLICATED_ROUTE')
170
+ }
171
+ })
@@ -96,15 +96,18 @@ test('Should expose router options via getters on request and reply', t => {
96
96
  const fastify = Fastify()
97
97
  const expectedSchema = {
98
98
  params: {
99
- id: { type: 'integer' }
99
+ type: 'object',
100
+ properties: {
101
+ id: { type: 'integer' }
102
+ }
100
103
  }
101
104
  }
102
105
 
103
106
  fastify.get('/test/:id', {
104
107
  schema: expectedSchema
105
108
  }, (req, reply) => {
106
- t.equal(reply.context.config.url, '/test/:id')
107
- t.equal(reply.context.config.method, 'GET')
109
+ t.equal(reply.routeOptions.config.url, '/test/:id')
110
+ t.equal(reply.routeOptions.config.method, 'GET')
108
111
  t.same(req.routeOptions.schema, expectedSchema)
109
112
  t.equal(typeof req.routeOptions.handler, 'function')
110
113
  t.equal(req.routeOptions.config.url, '/test/:id')
@@ -137,13 +137,19 @@ test('Example - validation', t => {
137
137
  }
138
138
 
139
139
  const queryStringJsonSchema = {
140
- name: { type: 'string' },
141
- excitement: { type: 'integer' }
140
+ type: 'object',
141
+ properties: {
142
+ name: { type: 'string' },
143
+ excitement: { type: 'integer' }
144
+ }
142
145
  }
143
146
 
144
147
  const paramsJsonSchema = {
145
- par1: { type: 'string' },
146
- par2: { type: 'number' }
148
+ type: 'object',
149
+ properties: {
150
+ par1: { type: 'string' },
151
+ par2: { type: 'number' }
152
+ }
147
153
  }
148
154
 
149
155
  const headersJsonSchema = {
@@ -345,8 +351,11 @@ test('Example - serializator', t => {
345
351
  schema: {
346
352
  response: {
347
353
  '2xx': {
348
- id: { type: 'number' },
349
- name: { type: 'string' }
354
+ type: 'object',
355
+ properties: {
356
+ id: { type: 'number' },
357
+ name: { type: 'string' }
358
+ }
350
359
  }
351
360
  }
352
361
  }