fastify 3.27.4 → 4.0.0-alpha.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 (168) hide show
  1. package/.taprc +3 -0
  2. package/README.md +7 -7
  3. package/build/build-error-serializer.js +27 -0
  4. package/build/build-validation.js +47 -35
  5. package/docs/Guides/Database.md +320 -0
  6. package/docs/Guides/Ecosystem.md +9 -0
  7. package/docs/Guides/Getting-Started.md +7 -7
  8. package/docs/Guides/Plugins-Guide.md +1 -1
  9. package/docs/Guides/Serverless.md +3 -3
  10. package/docs/Guides/Testing.md +2 -2
  11. package/docs/Migration-Guide-V4.md +12 -0
  12. package/docs/Reference/ContentTypeParser.md +4 -0
  13. package/docs/Reference/Decorators.md +2 -2
  14. package/docs/Reference/Encapsulation.md +2 -2
  15. package/docs/Reference/Errors.md +51 -6
  16. package/docs/Reference/HTTP2.md +3 -3
  17. package/docs/Reference/Hooks.md +4 -7
  18. package/docs/Reference/LTS.md +5 -4
  19. package/docs/Reference/Plugins.md +3 -3
  20. package/docs/Reference/Reply.md +73 -22
  21. package/docs/Reference/Request.md +1 -3
  22. package/docs/Reference/Routes.md +22 -15
  23. package/docs/Reference/Server.md +69 -119
  24. package/docs/Reference/TypeScript.md +20 -22
  25. package/docs/Reference/Validation-and-Serialization.md +30 -55
  26. package/docs/Type-Providers.md +257 -0
  27. package/examples/asyncawait.js +1 -1
  28. package/examples/benchmark/hooks-benchmark-async-await.js +1 -1
  29. package/examples/benchmark/hooks-benchmark.js +1 -1
  30. package/examples/benchmark/simple.js +1 -1
  31. package/examples/hooks.js +2 -2
  32. package/examples/http2.js +1 -1
  33. package/examples/https.js +1 -1
  34. package/examples/parser.js +13 -3
  35. package/examples/route-prefix.js +1 -1
  36. package/examples/shared-schema.js +1 -1
  37. package/examples/simple-stream.js +18 -0
  38. package/examples/simple.js +1 -1
  39. package/examples/simple.mjs +1 -1
  40. package/examples/typescript-server.ts +1 -1
  41. package/examples/use-plugin.js +1 -1
  42. package/fastify.d.ts +34 -22
  43. package/fastify.js +40 -36
  44. package/lib/configValidator.js +902 -1023
  45. package/lib/contentTypeParser.js +6 -16
  46. package/lib/context.js +36 -10
  47. package/lib/decorate.js +3 -1
  48. package/lib/error-handler.js +158 -0
  49. package/lib/error-serializer.js +257 -0
  50. package/lib/errors.js +51 -9
  51. package/lib/fourOhFour.js +31 -20
  52. package/lib/handleRequest.js +10 -13
  53. package/lib/hooks.js +14 -9
  54. package/lib/pluginOverride.js +0 -3
  55. package/lib/pluginUtils.js +3 -2
  56. package/lib/reply.js +121 -175
  57. package/lib/request.js +13 -10
  58. package/lib/route.js +131 -138
  59. package/lib/schema-controller.js +2 -2
  60. package/lib/schemas.js +27 -1
  61. package/lib/server.js +242 -116
  62. package/lib/symbols.js +5 -3
  63. package/lib/validation.js +11 -9
  64. package/lib/warnings.js +4 -12
  65. package/lib/wrapThenable.js +4 -11
  66. package/package.json +37 -39
  67. package/test/404s.test.js +258 -125
  68. package/test/500s.test.js +3 -3
  69. package/test/als.test.js +1 -1
  70. package/test/async-await.test.js +20 -76
  71. package/test/bodyLimit.test.js +1 -1
  72. package/test/build-certificate.js +6 -7
  73. package/test/case-insensitive.test.js +4 -4
  74. package/test/close-pipelining.test.js +2 -2
  75. package/test/close.test.js +11 -11
  76. package/test/content-parser.test.js +32 -0
  77. package/test/context-config.test.js +52 -0
  78. package/test/custom-http-server.test.js +14 -7
  79. package/test/custom-parser-async.test.js +1 -66
  80. package/test/custom-parser.test.js +92 -159
  81. package/test/custom-querystring-parser.test.js +3 -3
  82. package/test/decorator.test.js +11 -13
  83. package/test/delete.test.js +6 -6
  84. package/test/encapsulated-error-handler.test.js +50 -0
  85. package/test/esm/index.test.js +0 -14
  86. package/test/fastify-instance.test.js +4 -4
  87. package/test/fluent-schema.test.js +4 -4
  88. package/test/genReqId.test.js +1 -1
  89. package/test/get.test.js +4 -4
  90. package/test/handler-context.test.js +2 -2
  91. package/test/head.test.js +1 -1
  92. package/test/helper.js +19 -4
  93. package/test/hooks-async.test.js +15 -48
  94. package/test/hooks.on-ready.test.js +10 -5
  95. package/test/hooks.test.js +78 -119
  96. package/test/http2/closing.test.js +10 -16
  97. package/test/http2/constraint.test.js +1 -1
  98. package/test/http2/head.test.js +1 -1
  99. package/test/http2/plain.test.js +1 -1
  100. package/test/http2/secure-with-fallback.test.js +1 -1
  101. package/test/http2/secure.test.js +1 -1
  102. package/test/http2/unknown-http-method.test.js +4 -10
  103. package/test/https/custom-https-server.test.js +12 -6
  104. package/test/https/https.test.js +1 -1
  105. package/test/input-validation.js +3 -3
  106. package/test/internals/handleRequest.test.js +6 -43
  107. package/test/internals/initialConfig.test.js +41 -12
  108. package/test/internals/logger.test.js +2 -2
  109. package/test/internals/reply.test.js +317 -48
  110. package/test/internals/request.test.js +13 -7
  111. package/test/internals/server.test.js +88 -0
  112. package/test/listen.deprecated.test.js +202 -0
  113. package/test/listen.test.js +140 -145
  114. package/test/logger.test.js +82 -42
  115. package/test/maxRequestsPerSocket.test.js +8 -6
  116. package/test/middleware.test.js +2 -25
  117. package/test/nullable-validation.test.js +53 -16
  118. package/test/output-validation.test.js +1 -1
  119. package/test/plugin.test.js +47 -21
  120. package/test/pretty-print.test.js +22 -10
  121. package/test/promises.test.js +1 -1
  122. package/test/proto-poisoning.test.js +6 -6
  123. package/test/register.test.js +3 -3
  124. package/test/reply-error.test.js +126 -15
  125. package/test/reply-trailers.test.js +270 -0
  126. package/test/request-error.test.js +3 -6
  127. package/test/route-hooks.test.js +18 -18
  128. package/test/route-prefix.test.js +2 -1
  129. package/test/route.test.js +206 -22
  130. package/test/router-options.test.js +2 -2
  131. package/test/schema-examples.test.js +11 -5
  132. package/test/schema-feature.test.js +25 -20
  133. package/test/schema-serialization.test.js +9 -9
  134. package/test/schema-special-usage.test.js +5 -153
  135. package/test/schema-validation.test.js +9 -9
  136. package/test/skip-reply-send.test.js +2 -2
  137. package/test/stream.test.js +82 -23
  138. package/test/throw.test.js +8 -5
  139. package/test/trust-proxy.test.js +6 -6
  140. package/test/type-provider.test.js +20 -0
  141. package/test/types/fastify.test-d.ts +10 -18
  142. package/test/types/hooks.test-d.ts +61 -5
  143. package/test/types/import.js +2 -0
  144. package/test/types/import.ts +1 -0
  145. package/test/types/instance.test-d.ts +68 -17
  146. package/test/types/logger.test-d.ts +44 -15
  147. package/test/types/reply.test-d.ts +2 -1
  148. package/test/types/request.test-d.ts +71 -1
  149. package/test/types/route.test-d.ts +8 -2
  150. package/test/types/schema.test-d.ts +2 -39
  151. package/test/types/type-provider.test-d.ts +424 -0
  152. package/test/url-rewriting.test.js +3 -3
  153. package/test/validation-error-handling.test.js +8 -8
  154. package/test/versioned-routes.test.js +30 -18
  155. package/test/wrapThenable.test.js +7 -6
  156. package/types/content-type-parser.d.ts +17 -8
  157. package/types/hooks.d.ts +182 -85
  158. package/types/instance.d.ts +286 -118
  159. package/types/logger.d.ts +18 -104
  160. package/types/plugin.d.ts +10 -4
  161. package/types/reply.d.ts +18 -12
  162. package/types/request.d.ts +13 -8
  163. package/types/route.d.ts +62 -34
  164. package/types/schema.d.ts +1 -1
  165. package/types/type-provider.d.ts +99 -0
  166. package/types/utils.d.ts +1 -1
  167. package/lib/schema-compilers.js +0 -12
  168. package/test/emit-warning.test.js +0 -166
@@ -1,167 +1,18 @@
1
1
  'use strict'
2
2
 
3
3
  const { test } = require('tap')
4
- const Joi = require('@hapi/joi')
4
+ const Joi = require('joi')
5
5
  const AJV = require('ajv')
6
6
  const S = require('fluent-json-schema')
7
7
  const Fastify = require('..')
8
8
  const ajvMergePatch = require('ajv-merge-patch')
9
9
  const ajvErrors = require('ajv-errors')
10
10
 
11
- const buildValidatorAJV8 = require('@fastify/ajv-compiler-8')
12
-
13
- test('Ajv8 usage instead of the bundle one', t => {
14
- t.plan(2)
15
-
16
- t.test('use new ajv8 option', t => {
17
- t.plan(2)
18
- const fastify = Fastify({
19
- ajv: {
20
- customOptions: { strictRequired: true }
21
- },
22
- schemaController: {
23
- compilersFactory: {
24
- buildValidator: buildValidatorAJV8()
25
- }
26
- }
27
- })
28
-
29
- fastify.post('/', {
30
- schema: {
31
- body: {
32
- type: 'object',
33
- required: ['missing'],
34
- properties: {
35
- foo: {
36
- type: 'string'
37
- }
38
- }
39
- }
40
- },
41
- handler (req, reply) { reply.send({ ok: 1 }) }
42
- })
43
-
44
- fastify.ready(err => {
45
- t.ok(err)
46
- t.match(err.message, 'strictRequired', 'the new ajv8 option trigger a startup error')
47
- })
48
- })
49
-
50
- t.test('use new ajv8 option within a response schema', t => {
51
- t.plan(2)
52
- const fastify = Fastify({
53
- schemaController: {
54
- compilersFactory: {
55
- buildValidator: buildValidatorAJV8()
56
- }
57
- }
58
- })
59
-
60
- fastify.post('/', {
61
- schema: {
62
- body: {
63
- type: 'object',
64
- required: ['missing'],
65
- properties: {
66
- foo: {
67
- type: 'string'
68
- }
69
- }
70
- },
71
- response: {
72
- '2xx': {
73
- type: 'object',
74
- properties: {
75
- ok: {
76
- type: 'integer'
77
- }
78
- }
79
- }
80
- }
81
- },
82
- handler (req, reply) { reply.send({ ok: 1 }) }
83
- })
84
-
85
- fastify.ready(err => {
86
- t.error(err)
87
- t.pass('startup successful')
88
- })
89
- })
90
- })
91
-
92
- test('Ajv8 usage with plugins', t => {
93
- t.plan(2)
94
-
95
- t.test('use new ajv8 option', t => {
96
- t.plan(3)
97
- const fastify = Fastify({
98
- ajv: {
99
- customOptions: { validateFormats: true },
100
- plugins: [require('ajv-formats')]
101
- },
102
- schemaController: {
103
- compilersFactory: {
104
- buildValidator: buildValidatorAJV8()
105
- }
106
- }
107
- })
108
-
109
- callIt(fastify, (err, res) => {
110
- t.error(err)
111
- t.equal(res.statusCode, 400)
112
- t.equal(res.json().message, 'body must match format "date"')
113
- })
114
- })
115
-
116
- t.test('use new ajv8 option - avoid check', t => {
117
- t.plan(2)
118
- const fastify = Fastify({
119
- ajv: {
120
- customOptions: { validateFormats: false }
121
- },
122
- schemaController: {
123
- compilersFactory: {
124
- buildValidator: buildValidatorAJV8()
125
- }
126
- }
127
- })
128
-
129
- callIt(fastify, (err, res) => {
130
- t.error(err)
131
- t.equal(res.statusCode, 200)
132
- })
133
- })
134
-
135
- function callIt (fastify, cb) {
136
- fastify.post('/', {
137
- schema: {
138
- body: {
139
- type: 'object',
140
- properties: {
141
- foo: {
142
- type: 'string',
143
- format: 'date'
144
- }
145
- }
146
- }
147
- },
148
- handler (req, reply) { reply.send({ ok: 1 }) }
149
- })
150
-
151
- fastify.inject({
152
- method: 'POST',
153
- url: '/',
154
- payload: { foo: '99' }
155
- }, cb)
156
- }
157
- })
158
-
159
11
  test('Ajv plugins array parameter', t => {
160
12
  t.plan(3)
161
13
  const fastify = Fastify({
162
14
  ajv: {
163
15
  customOptions: {
164
- jsonPointers: true,
165
16
  allErrors: true
166
17
  },
167
18
  plugins: [
@@ -509,7 +360,7 @@ test('setSchemaController in a plugin', t => {
509
360
  ajvInstance.addSchema(baseSchema)
510
361
  ajvInstance.addSchema(refSchema)
511
362
 
512
- const fastify = Fastify()
363
+ const fastify = Fastify({ exposeHeadRoutes: false })
513
364
  fastify.register(schemaPlugin)
514
365
  fastify.get('/', {
515
366
  schema: {
@@ -760,7 +611,8 @@ test('multiple refs with the same ids', t => {
760
611
 
761
612
  fastify.addSchema(baseSchema)
762
613
  fastify.addSchema(refSchema)
763
- fastify.get('/', {
614
+
615
+ fastify.head('/', {
764
616
  schema: {
765
617
  query: refSchema,
766
618
  response: {
@@ -772,7 +624,7 @@ test('multiple refs with the same ids', t => {
772
624
  }
773
625
  })
774
626
 
775
- fastify.head('/', {
627
+ fastify.get('/', {
776
628
  schema: {
777
629
  query: refSchema,
778
630
  response: {
@@ -99,7 +99,7 @@ test('Basic validation test', t => {
99
99
  url: '/'
100
100
  }, (err, res) => {
101
101
  t.error(err)
102
- t.same(res.json(), { statusCode: 400, error: 'Bad Request', message: "body should have required property 'work'" })
102
+ t.same(res.json(), { statusCode: 400, error: 'Bad Request', message: "body must have required property 'work'" })
103
103
  t.equal(res.statusCode, 400)
104
104
  })
105
105
  })
@@ -314,7 +314,7 @@ test('Triple $ref with a simple $id', t => {
314
314
  }, (err, res) => {
315
315
  t.error(err)
316
316
  t.equal(res.statusCode, 400)
317
- t.same(res.json().message, "body should have required property 'foo'")
317
+ t.same(res.json().message, "body must have required property 'foo'")
318
318
  })
319
319
  })
320
320
 
@@ -348,6 +348,7 @@ test('Extending schema', t => {
348
348
  allOf: [
349
349
  { $ref: 'address.id#/definitions/address' },
350
350
  {
351
+ type: 'object',
351
352
  properties: { type: { enum: ['residential', 'business'] } },
352
353
  required: ['type']
353
354
  }
@@ -439,7 +440,7 @@ test('Should work with nested ids', t => {
439
440
  }, (err, res) => {
440
441
  t.error(err)
441
442
  t.equal(res.statusCode, 400)
442
- t.equal(res.json().message, 'params.id should be number')
443
+ t.equal(res.json().message, 'params/id must be number')
443
444
  })
444
445
  })
445
446
 
@@ -536,7 +537,7 @@ test('JSON Schema validation keywords', t => {
536
537
  t.same(res.json(), {
537
538
  statusCode: 400,
538
539
  error: 'Bad Request',
539
- message: 'params.ip should match format "ipv4"'
540
+ message: 'params/ip must match format "ipv4"'
540
541
  })
541
542
  })
542
543
  })
@@ -590,7 +591,7 @@ test('Nested id calls', t => {
590
591
  t.equal(res.statusCode, 400)
591
592
  t.same(res.json(), {
592
593
  error: 'Bad Request',
593
- message: 'body.host.ip should match format "ipv4"',
594
+ message: 'body/host/ip must match format "ipv4"',
594
595
  statusCode: 400
595
596
  })
596
597
  })
@@ -692,7 +693,7 @@ test('Use shared schema and $ref with $id ($ref to $id)', t => {
692
693
  t.equal(res.statusCode, 400)
693
694
  t.same(res.json(), {
694
695
  error: 'Bad Request',
695
- message: "body should have required property 'address'",
696
+ message: "body must have required property 'address'",
696
697
  statusCode: 400
697
698
  })
698
699
  })
@@ -712,8 +713,7 @@ test('Use items with $ref', t => {
712
713
 
713
714
  const body = {
714
715
  type: 'array',
715
- items: { $ref: 'http://example.com/ref-to-external-validator.json#' },
716
- default: []
716
+ items: { $ref: 'http://example.com/ref-to-external-validator.json#' }
717
717
  }
718
718
 
719
719
  fastify.post('/', {
@@ -809,7 +809,7 @@ test('Use $ref to /definitions', t => {
809
809
  t.equal(res.statusCode, 400)
810
810
  t.same(res.json(), {
811
811
  error: 'Bad Request',
812
- message: 'body.test.id should be number',
812
+ message: 'body/test/id must be number',
813
813
  statusCode: 400
814
814
  })
815
815
  })
@@ -201,7 +201,7 @@ function testHandlerOrBeforeHandlerHook (test, hookOrHandler) {
201
201
 
202
202
  nextHooks.forEach(h => app.addHook(h, async (req, reply) => t.fail(`${h} should not be called`)))
203
203
 
204
- app.listen(0, err => {
204
+ app.listen({ port: 0 }, err => {
205
205
  t.error(err)
206
206
  const client = net.createConnection({ port: (app.server.address()).port }, () => {
207
207
  client.write('GET / HTTP/1.1\r\n\r\n')
@@ -297,7 +297,7 @@ function testHandlerOrBeforeHandlerHook (test, hookOrHandler) {
297
297
  } else {
298
298
  app.addHook(hookOrHandler, async (req, reply) => {
299
299
  reply.hijack()
300
- reply.send('hello from reply.send()')
300
+ return reply.send('hello from reply.send()')
301
301
  })
302
302
  app.get('/', (req, reply) => t.fail('Handler should not be called'))
303
303
  }
@@ -14,7 +14,8 @@ const JSONStream = require('JSONStream')
14
14
  const send = require('send')
15
15
  const Readable = require('stream').Readable
16
16
  const split = require('split2')
17
- const { kDisableRequestLogging, kReplySent } = require('../lib/symbols.js')
17
+ const semver = require('semver')
18
+ const { kDisableRequestLogging } = require('../lib/symbols.js')
18
19
 
19
20
  function getUrl (app) {
20
21
  const { address, port } = app.server.address()
@@ -26,7 +27,7 @@ function getUrl (app) {
26
27
  }
27
28
 
28
29
  test('should respond with a stream', t => {
29
- t.plan(8)
30
+ t.plan(6)
30
31
  const fastify = Fastify()
31
32
 
32
33
  fastify.get('/', function (req, reply) {
@@ -34,18 +35,13 @@ test('should respond with a stream', t => {
34
35
  reply.code(200).send(stream)
35
36
  })
36
37
 
37
- fastify.get('/error', function (req, reply) {
38
- const stream = fs.createReadStream('not-existing-file', 'utf8')
39
- reply.code(200).send(stream)
40
- })
41
-
42
- fastify.listen(0, err => {
38
+ fastify.listen({ port: 0 }, err => {
43
39
  t.error(err)
44
40
  fastify.server.unref()
45
41
 
46
42
  sget(`http://localhost:${fastify.server.address().port}`, function (err, response, data) {
47
43
  t.error(err)
48
- t.equal(response.headers['content-type'], 'application/octet-stream')
44
+ t.equal(response.headers['content-type'], undefined)
49
45
  t.equal(response.statusCode, 200)
50
46
 
51
47
  fs.readFile(__filename, (err, expected) => {
@@ -53,6 +49,21 @@ test('should respond with a stream', t => {
53
49
  t.equal(expected.toString(), data.toString())
54
50
  })
55
51
  })
52
+ })
53
+ })
54
+
55
+ test('should respond with a stream (error)', t => {
56
+ t.plan(3)
57
+ const fastify = Fastify()
58
+
59
+ fastify.get('/error', function (req, reply) {
60
+ const stream = fs.createReadStream('not-existing-file', 'utf8')
61
+ reply.code(200).send(stream)
62
+ })
63
+
64
+ fastify.listen({ port: 0 }, err => {
65
+ t.error(err)
66
+ fastify.server.unref()
56
67
 
57
68
  sget(`http://localhost:${fastify.server.address().port}/error`, function (err, response) {
58
69
  t.error(err)
@@ -105,7 +116,7 @@ test('should trigger the onSend hook only twice if pumping the stream fails, fir
105
116
  done()
106
117
  })
107
118
 
108
- fastify.listen(0, err => {
119
+ fastify.listen({ port: 0 }, err => {
109
120
  t.error(err)
110
121
 
111
122
  fastify.server.unref()
@@ -268,7 +279,7 @@ test('Destroying streams prematurely', t => {
268
279
  reply.send(reallyLongStream)
269
280
  })
270
281
 
271
- fastify.listen(0, err => {
282
+ fastify.listen({ port: 0 }, err => {
272
283
  t.error(err)
273
284
  fastify.server.unref()
274
285
 
@@ -331,7 +342,7 @@ test('Destroying streams prematurely should call close method', t => {
331
342
  reply.send(reallyLongStream)
332
343
  })
333
344
 
334
- fastify.listen(0, err => {
345
+ fastify.listen({ port: 0 }, err => {
335
346
  t.error(err)
336
347
  fastify.server.unref()
337
348
 
@@ -393,7 +404,7 @@ test('Destroying streams prematurely should call close method when destroy is no
393
404
  reply.send(reallyLongStream)
394
405
  })
395
406
 
396
- fastify.listen(0, err => {
407
+ fastify.listen({ port: 0 }, err => {
397
408
  t.error(err)
398
409
  fastify.server.unref()
399
410
 
@@ -456,7 +467,7 @@ test('Destroying streams prematurely should call abort method', t => {
456
467
  reply.send(reallyLongStream)
457
468
  })
458
469
 
459
- fastify.listen(0, err => {
470
+ fastify.listen({ port: 0 }, err => {
460
471
  t.error(err)
461
472
  fastify.server.unref()
462
473
 
@@ -506,7 +517,7 @@ test('Destroying streams prematurely, log is disabled', t => {
506
517
  reply.send(reallyLongStream)
507
518
  })
508
519
 
509
- fastify.listen(0, err => {
520
+ fastify.listen({ port: 0 }, err => {
510
521
  t.error(err)
511
522
  fastify.server.unref()
512
523
 
@@ -536,7 +547,7 @@ test('should respond with a stream1', t => {
536
547
  stream.end({ a: 42 })
537
548
  })
538
549
 
539
- fastify.listen(0, err => {
550
+ fastify.listen({ port: 0 }, err => {
540
551
  t.error(err)
541
552
  fastify.server.unref()
542
553
 
@@ -568,7 +579,7 @@ test('return a 404 if the stream emits a 404 error', t => {
568
579
  reply.send(reallyLongStream)
569
580
  })
570
581
 
571
- fastify.listen(0, err => {
582
+ fastify.listen({ port: 0 }, err => {
572
583
  t.error(err)
573
584
  fastify.server.unref()
574
585
 
@@ -582,7 +593,7 @@ test('return a 404 if the stream emits a 404 error', t => {
582
593
  })
583
594
  })
584
595
 
585
- test('should support send module 200 and 404', { only: true }, t => {
596
+ test('should support send module 200 and 404', { skip: semver.gte(process.versions.node, '17.0.0') }, t => {
586
597
  t.plan(8)
587
598
  const fastify = Fastify()
588
599
 
@@ -596,7 +607,7 @@ test('should support send module 200 and 404', { only: true }, t => {
596
607
  reply.code(200).send(stream)
597
608
  })
598
609
 
599
- fastify.listen(0, err => {
610
+ fastify.listen({ port: 0 }, err => {
600
611
  t.error(err)
601
612
  fastify.server.unref()
602
613
 
@@ -604,7 +615,7 @@ test('should support send module 200 and 404', { only: true }, t => {
604
615
 
605
616
  sget(url, function (err, response, data) {
606
617
  t.error(err)
607
- t.equal(response.headers['content-type'], 'application/octet-stream')
618
+ t.equal(response.headers['content-type'], 'application/javascript; charset=UTF-8')
608
619
  t.equal(response.statusCode, 200)
609
620
 
610
621
  fs.readFile(__filename, (err, expected) => {
@@ -637,7 +648,7 @@ test('should destroy stream when response is ended', t => {
637
648
  reply.raw.end(Buffer.from('hello\n'))
638
649
  })
639
650
 
640
- fastify.listen(0, err => {
651
+ fastify.listen({ port: 0 }, err => {
641
652
  t.error(err)
642
653
  fastify.server.unref()
643
654
 
@@ -654,7 +665,7 @@ test('should mark reply as sent before pumping the payload stream into response
654
665
  const handleRequest = proxyquire('../lib/handleRequest', {
655
666
  './wrapThenable': (thenable, reply) => {
656
667
  thenable.then(function (payload) {
657
- t.equal(reply[kReplySent], true)
668
+ t.equal(reply.sent, true)
658
669
  })
659
670
  }
660
671
  })
@@ -671,7 +682,7 @@ test('should mark reply as sent before pumping the payload stream into response
671
682
 
672
683
  fastify.get('/', async function (req, reply) {
673
684
  const stream = fs.createReadStream(__filename, 'utf8')
674
- reply.code(200).send(stream)
685
+ return reply.code(200).send(stream)
675
686
  })
676
687
 
677
688
  fastify.inject({
@@ -683,3 +694,51 @@ test('should mark reply as sent before pumping the payload stream into response
683
694
  fastify.close()
684
695
  })
685
696
  })
697
+
698
+ test('reply.send handles aborted requests', t => {
699
+ t.plan(2)
700
+
701
+ const spyLogger = {
702
+ level: 'error',
703
+ fatal: () => { },
704
+ error: () => {
705
+ t.fail('should not log an error')
706
+ },
707
+ warn: () => { },
708
+ info: () => { },
709
+ debug: () => { },
710
+ trace: () => { },
711
+ child: () => { return spyLogger }
712
+ }
713
+ const fastify = Fastify({
714
+ logger: spyLogger
715
+ })
716
+
717
+ fastify.get('/', (req, reply) => {
718
+ setTimeout(() => {
719
+ const stream = new Readable({
720
+ read: function () {
721
+ this.push(null)
722
+ }
723
+ })
724
+ reply.send(stream)
725
+ }, 6)
726
+ })
727
+
728
+ fastify.listen({ port: 0 }, err => {
729
+ t.error(err)
730
+ fastify.server.unref()
731
+
732
+ const port = fastify.server.address().port
733
+ const http = require('http')
734
+ const req = http.get(`http://localhost:${port}`)
735
+ .on('error', (err) => {
736
+ t.equal(err.code, 'ECONNRESET')
737
+ fastify.close()
738
+ })
739
+
740
+ setTimeout(() => {
741
+ req.abort()
742
+ }, 1)
743
+ })
744
+ })
@@ -17,12 +17,15 @@ test('Fastify should throw on wrong options', t => {
17
17
  test('Fastify should throw on multiple assignment to the same route', t => {
18
18
  t.plan(1)
19
19
  const fastify = Fastify()
20
- fastify.get('/', () => {})
20
+
21
21
  fastify.get('/', () => {})
22
22
 
23
- fastify.ready(err => {
24
- t.equal(err.message, "Method 'GET' already declared for route '/' with constraints '{}'")
25
- })
23
+ try {
24
+ fastify.get('/', () => {})
25
+ t.fail('Should throw on duplicated route declaration')
26
+ } catch (error) {
27
+ t.equal(error.message, "Method 'GET' already declared for route '/'")
28
+ }
26
29
  })
27
30
 
28
31
  test('Fastify should throw for an invalid schema, printing the error route - headers', t => {
@@ -78,7 +81,7 @@ test('Fastify should throw for an invalid shorthand option type', t => {
78
81
  t.fail()
79
82
  } catch (e) {
80
83
  t.equal(e.code, 'FST_ERR_INIT_OPTS_INVALID')
81
- t.match(e.message, /should be boolean/)
84
+ t.match(e.message, /must be boolean/)
82
85
  t.pass()
83
86
  }
84
87
  })
@@ -63,7 +63,7 @@ test('trust proxy, not add properties to node req', (t) => {
63
63
 
64
64
  t.teardown(app.close.bind(app))
65
65
 
66
- app.listen(0, (err) => {
66
+ app.listen({ port: 0 }, (err) => {
67
67
  app.server.unref()
68
68
  t.error(err)
69
69
  sgetForwardedRequest(app, '1.1.1.1', '/trustproxy')
@@ -84,7 +84,7 @@ test('trust proxy chain', (t) => {
84
84
 
85
85
  t.teardown(app.close.bind(app))
86
86
 
87
- app.listen(0, (err) => {
87
+ app.listen({ port: 0 }, (err) => {
88
88
  app.server.unref()
89
89
  t.error(err)
90
90
  sgetForwardedRequest(app, '192.168.1.1, 1.1.1.1', '/trustproxychain')
@@ -103,7 +103,7 @@ test('trust proxy function', (t) => {
103
103
 
104
104
  t.teardown(app.close.bind(app))
105
105
 
106
- app.listen(0, (err) => {
106
+ app.listen({ port: 0 }, (err) => {
107
107
  app.server.unref()
108
108
  t.error(err)
109
109
  sgetForwardedRequest(app, '1.1.1.1', '/trustproxyfunc')
@@ -122,7 +122,7 @@ test('trust proxy number', (t) => {
122
122
 
123
123
  t.teardown(app.close.bind(app))
124
124
 
125
- app.listen(0, (err) => {
125
+ app.listen({ port: 0 }, (err) => {
126
126
  app.server.unref()
127
127
  t.error(err)
128
128
  sgetForwardedRequest(app, '2.2.2.2, 1.1.1.1', '/trustproxynumber')
@@ -141,7 +141,7 @@ test('trust proxy IP addresses', (t) => {
141
141
 
142
142
  t.teardown(app.close.bind(app))
143
143
 
144
- app.listen(0, (err) => {
144
+ app.listen({ port: 0 }, (err) => {
145
145
  app.server.unref()
146
146
  t.error(err)
147
147
  sgetForwardedRequest(app, '3.3.3.3, 2.2.2.2, 1.1.1.1', '/trustproxyipaddrs')
@@ -168,7 +168,7 @@ test('trust proxy protocol', (t) => {
168
168
 
169
169
  t.teardown(app.close.bind(app))
170
170
 
171
- app.listen(0, (err) => {
171
+ app.listen({ port: 0 }, (err) => {
172
172
  app.server.unref()
173
173
  t.error(err)
174
174
  sgetForwardedRequest(app, '1.1.1.1', '/trustproxyprotocol', 'lorem')
@@ -0,0 +1,20 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('tap')
4
+ const Fastify = require('..')
5
+
6
+ test('Should export withTypeProvider function', t => {
7
+ t.plan(1)
8
+ try {
9
+ Fastify().withTypeProvider()
10
+ t.pass()
11
+ } catch (e) {
12
+ t.fail()
13
+ }
14
+ })
15
+
16
+ test('Should return same instance', t => {
17
+ t.plan(1)
18
+ const fastify = Fastify()
19
+ t.equal(fastify, fastify.withTypeProvider())
20
+ })