fastify 4.17.0 → 4.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/GOVERNANCE.md +2 -2
  2. package/README.md +13 -10
  3. package/docs/Guides/Ecosystem.md +6 -0
  4. package/docs/Guides/Serverless.md +12 -1
  5. package/docs/Reference/Errors.md +5 -0
  6. package/docs/Reference/LTS.md +5 -5
  7. package/docs/Reference/Lifecycle.md +3 -0
  8. package/docs/Reference/Logging.md +34 -1
  9. package/docs/Reference/Reply.md +19 -0
  10. package/docs/Reference/Request.md +1 -1
  11. package/docs/Reference/Server.md +20 -2
  12. package/docs/Reference/Validation-and-Serialization.md +3 -2
  13. package/examples/benchmark/body.json +3 -0
  14. package/fastify.d.ts +6 -1
  15. package/fastify.js +17 -12
  16. package/lib/contentTypeParser.js +3 -1
  17. package/lib/errors.js +5 -0
  18. package/lib/handleRequest.js +15 -4
  19. package/lib/reply.js +3 -2
  20. package/lib/route.js +14 -3
  21. package/lib/schemas.js +18 -21
  22. package/lib/server.js +9 -4
  23. package/lib/validation.js +98 -16
  24. package/package.json +33 -33
  25. package/test/custom-parser.0.test.js +777 -0
  26. package/test/{custom-parser.test.js → custom-parser.1.test.js} +1 -742
  27. package/test/fastify-instance.test.js +39 -0
  28. package/test/hooks-async.test.js +154 -0
  29. package/test/hooks.test.js +29 -29
  30. package/test/internals/reply.test.js +114 -45
  31. package/test/internals/validation.test.js +58 -0
  32. package/test/reply-error.test.js +7 -7
  33. package/test/request-error.test.js +3 -0
  34. package/test/route-hooks.test.js +38 -0
  35. package/test/route.test.js +192 -74
  36. package/test/schema-special-usage.test.js +569 -0
  37. package/test/types/fastify.test-d.ts +4 -1
  38. package/test/types/instance.test-d.ts +1 -0
  39. package/test/types/logger.test-d.ts +10 -4
  40. package/test/types/reply.test-d.ts +4 -1
  41. package/test/types/route.test-d.ts +12 -0
  42. package/test/url-rewriting.test.js +3 -0
  43. package/types/.eslintrc.json +1 -1
  44. package/types/instance.d.ts +1 -1
  45. package/types/logger.d.ts +10 -1
  46. package/types/reply.d.ts +7 -1
  47. package/types/type-provider.d.ts +0 -1
  48. package/types/utils.d.ts +3 -1
  49. /package/types/{tsconfig.json → tsconfig.eslint.json} +0 -0
@@ -8,7 +8,11 @@ const sget = require('simple-get').concat
8
8
  const joi = require('joi')
9
9
  const Fastify = require('..')
10
10
  const proxyquire = require('proxyquire')
11
- const { FST_ERR_INVALID_URL } = require('../lib/errors')
11
+ const {
12
+ FST_ERR_INVALID_URL,
13
+ FST_ERR_INSTANCE_ALREADY_LISTENING,
14
+ FST_ERR_ROUTE_METHOD_INVALID
15
+ } = require('../lib/errors')
12
16
 
13
17
  function getUrl (app) {
14
18
  const { address, port } = app.server.address()
@@ -20,13 +24,14 @@ function getUrl (app) {
20
24
  }
21
25
 
22
26
  test('route', t => {
23
- t.plan(9)
27
+ t.plan(10)
24
28
  const test = t.test
25
- const fastify = Fastify()
26
29
 
27
30
  test('route - get', t => {
28
- t.plan(1)
29
- try {
31
+ t.plan(4)
32
+
33
+ const fastify = Fastify()
34
+ t.doesNotThrow(() =>
30
35
  fastify.route({
31
36
  method: 'GET',
32
37
  url: '/',
@@ -46,15 +51,27 @@ test('route', t => {
46
51
  reply.send({ hello: 'world' })
47
52
  }
48
53
  })
49
- t.pass()
50
- } catch (e) {
51
- t.fail()
52
- }
54
+ )
55
+
56
+ fastify.listen({ port: 0 }, function (err) {
57
+ if (err) t.error(err)
58
+ t.teardown(() => { fastify.close() })
59
+ sget({
60
+ method: 'GET',
61
+ url: getUrl(fastify) + '/'
62
+ }, (err, response, body) => {
63
+ t.error(err)
64
+ t.equal(response.statusCode, 200)
65
+ t.same(JSON.parse(body), { hello: 'world' })
66
+ })
67
+ })
53
68
  })
54
69
 
55
70
  test('missing schema - route', t => {
56
- t.plan(1)
57
- try {
71
+ t.plan(4)
72
+
73
+ const fastify = Fastify()
74
+ t.doesNotThrow(() =>
58
75
  fastify.route({
59
76
  method: 'GET',
60
77
  url: '/missing',
@@ -62,106 +79,188 @@ test('route', t => {
62
79
  reply.send({ hello: 'world' })
63
80
  }
64
81
  })
65
- t.pass()
66
- } catch (e) {
67
- t.fail()
68
- }
82
+ )
83
+
84
+ fastify.listen({ port: 0 }, function (err) {
85
+ if (err) t.error(err)
86
+ t.teardown(() => { fastify.close() })
87
+ sget({
88
+ method: 'GET',
89
+ url: getUrl(fastify) + '/missing'
90
+ }, (err, response, body) => {
91
+ t.error(err)
92
+ t.equal(response.statusCode, 200)
93
+ t.same(JSON.parse(body), { hello: 'world' })
94
+ })
95
+ })
69
96
  })
70
97
 
71
98
  test('invalid handler attribute - route', t => {
72
99
  t.plan(1)
73
- try {
74
- fastify.get('/', { handler: 'not a function' }, () => {})
75
- t.fail()
76
- } catch (e) {
77
- t.pass()
78
- }
100
+
101
+ const fastify = Fastify()
102
+ t.throws(() => fastify.get('/', { handler: 'not a function' }, () => { }))
79
103
  })
80
104
 
81
- test('Multiple methods', t => {
82
- t.plan(1)
83
- try {
105
+ test('Add Multiple methods per route all uppercase', t => {
106
+ t.plan(7)
107
+
108
+ const fastify = Fastify()
109
+ t.doesNotThrow(() =>
84
110
  fastify.route({
85
111
  method: ['GET', 'DELETE'],
86
112
  url: '/multiple',
87
113
  handler: function (req, reply) {
88
114
  reply.send({ hello: 'world' })
89
115
  }
116
+ }))
117
+
118
+ fastify.listen({ port: 0 }, function (err) {
119
+ if (err) t.error(err)
120
+ t.teardown(() => { fastify.close() })
121
+ sget({
122
+ method: 'GET',
123
+ url: getUrl(fastify) + '/multiple'
124
+ }, (err, response, body) => {
125
+ t.error(err)
126
+ t.equal(response.statusCode, 200)
127
+ t.same(JSON.parse(body), { hello: 'world' })
90
128
  })
91
- t.pass()
92
- } catch (e) {
93
- t.fail()
94
- }
95
- })
96
129
 
97
- test('Add multiple methods', t => {
98
- t.plan(1)
99
- try {
100
- fastify.get('/add-multiple', function (req, reply) {
101
- reply.send({ hello: 'Bob!' })
130
+ sget({
131
+ method: 'DELETE',
132
+ url: getUrl(fastify) + '/multiple'
133
+ }, (err, response, body) => {
134
+ t.error(err)
135
+ t.equal(response.statusCode, 200)
136
+ t.same(JSON.parse(body), { hello: 'world' })
102
137
  })
138
+ })
139
+ })
140
+
141
+ test('Add Multiple methods per route all lowercase', t => {
142
+ t.plan(7)
143
+
144
+ const fastify = Fastify()
145
+ t.doesNotThrow(() =>
103
146
  fastify.route({
104
- method: ['PUT', 'DELETE'],
105
- url: '/add-multiple',
147
+ method: ['get', 'delete'],
148
+ url: '/multiple',
106
149
  handler: function (req, reply) {
107
150
  reply.send({ hello: 'world' })
108
151
  }
152
+ }))
153
+
154
+ fastify.listen({ port: 0 }, function (err) {
155
+ if (err) t.error(err)
156
+ t.teardown(() => { fastify.close() })
157
+ sget({
158
+ method: 'GET',
159
+ url: getUrl(fastify) + '/multiple'
160
+ }, (err, response, body) => {
161
+ t.error(err)
162
+ t.equal(response.statusCode, 200)
163
+ t.same(JSON.parse(body), { hello: 'world' })
109
164
  })
110
- t.pass()
111
- } catch (e) {
112
- t.fail()
113
- }
165
+
166
+ sget({
167
+ method: 'DELETE',
168
+ url: getUrl(fastify) + '/multiple'
169
+ }, (err, response, body) => {
170
+ t.error(err)
171
+ t.equal(response.statusCode, 200)
172
+ t.same(JSON.parse(body), { hello: 'world' })
173
+ })
174
+ })
114
175
  })
115
176
 
116
- fastify.listen({ port: 0 }, function (err) {
117
- if (err) t.error(err)
118
- t.teardown(() => { fastify.close() })
177
+ test('Add Multiple methods per route mixed uppercase and lowercase', t => {
178
+ t.plan(7)
119
179
 
120
- test('cannot add another route after binding', t => {
121
- t.plan(1)
122
- try {
123
- fastify.route({
124
- method: 'GET',
125
- url: '/another-get-route',
126
- handler: function (req, reply) {
127
- reply.send({ hello: 'world' })
128
- }
129
- })
130
- t.fail()
131
- } catch (e) {
132
- t.pass()
133
- }
134
- })
180
+ const fastify = Fastify()
181
+ t.doesNotThrow(() =>
182
+ fastify.route({
183
+ method: ['GET', 'delete'],
184
+ url: '/multiple',
185
+ handler: function (req, reply) {
186
+ reply.send({ hello: 'world' })
187
+ }
188
+ }))
135
189
 
136
- test('route - get', t => {
137
- t.plan(3)
190
+ fastify.listen({ port: 0 }, function (err) {
191
+ if (err) t.error(err)
192
+ t.teardown(() => { fastify.close() })
138
193
  sget({
139
194
  method: 'GET',
140
- url: 'http://localhost:' + fastify.server.address().port
195
+ url: getUrl(fastify) + '/multiple'
141
196
  }, (err, response, body) => {
142
197
  t.error(err)
143
198
  t.equal(response.statusCode, 200)
144
199
  t.same(JSON.parse(body), { hello: 'world' })
145
200
  })
146
- })
147
201
 
148
- test('route - missing schema', t => {
149
- t.plan(3)
150
202
  sget({
151
- method: 'GET',
152
- url: 'http://localhost:' + fastify.server.address().port + '/missing'
203
+ method: 'DELETE',
204
+ url: getUrl(fastify) + '/multiple'
153
205
  }, (err, response, body) => {
154
206
  t.error(err)
155
207
  t.equal(response.statusCode, 200)
156
208
  t.same(JSON.parse(body), { hello: 'world' })
157
209
  })
158
210
  })
211
+ })
212
+
213
+ test('Add invalid Multiple methods per route', t => {
214
+ t.plan(1)
215
+
216
+ const fastify = Fastify()
217
+ t.throws(() =>
218
+ fastify.route({
219
+ method: ['GET', 1],
220
+ url: '/invalid-method',
221
+ handler: function (req, reply) {
222
+ reply.send({ hello: 'world' })
223
+ }
224
+ }), new FST_ERR_ROUTE_METHOD_INVALID())
225
+ })
226
+
227
+ test('Add method', t => {
228
+ t.plan(1)
159
229
 
160
- test('route - multiple methods', t => {
161
- t.plan(6)
230
+ const fastify = Fastify()
231
+ t.throws(() =>
232
+ fastify.route({
233
+ method: 1,
234
+ url: '/invalid-method',
235
+ handler: function (req, reply) {
236
+ reply.send({ hello: 'world' })
237
+ }
238
+ }), new FST_ERR_ROUTE_METHOD_INVALID())
239
+ })
240
+
241
+ test('Add additional multiple methods to existing route', t => {
242
+ t.plan(7)
243
+
244
+ const fastify = Fastify()
245
+ t.doesNotThrow(() => {
246
+ fastify.get('/add-multiple', function (req, reply) {
247
+ reply.send({ hello: 'Bob!' })
248
+ })
249
+ fastify.route({
250
+ method: ['PUT', 'DELETE'],
251
+ url: '/add-multiple',
252
+ handler: function (req, reply) {
253
+ reply.send({ hello: 'world' })
254
+ }
255
+ })
256
+ })
257
+
258
+ fastify.listen({ port: 0 }, function (err) {
259
+ if (err) t.error(err)
260
+ t.teardown(() => { fastify.close() })
162
261
  sget({
163
- method: 'GET',
164
- url: 'http://localhost:' + fastify.server.address().port + '/multiple'
262
+ method: 'PUT',
263
+ url: getUrl(fastify) + '/add-multiple'
165
264
  }, (err, response, body) => {
166
265
  t.error(err)
167
266
  t.equal(response.statusCode, 200)
@@ -170,7 +269,7 @@ test('route', t => {
170
269
 
171
270
  sget({
172
271
  method: 'DELETE',
173
- url: 'http://localhost:' + fastify.server.address().port + '/multiple'
272
+ url: getUrl(fastify) + '/add-multiple'
174
273
  }, (err, response, body) => {
175
274
  t.error(err)
176
275
  t.equal(response.statusCode, 200)
@@ -178,6 +277,25 @@ test('route', t => {
178
277
  })
179
278
  })
180
279
  })
280
+
281
+ test('cannot add another route after binding', t => {
282
+ t.plan(1)
283
+
284
+ const fastify = Fastify()
285
+
286
+ fastify.listen({ port: 0 }, function (err) {
287
+ if (err) t.error(err)
288
+ t.teardown(() => { fastify.close() })
289
+
290
+ t.throws(() => fastify.route({
291
+ method: 'GET',
292
+ url: '/another-get-route',
293
+ handler: function (req, reply) {
294
+ reply.send({ hello: 'world' })
295
+ }
296
+ }), new FST_ERR_INSTANCE_ALREADY_LISTENING('Cannot add route!'))
297
+ })
298
+ })
181
299
  })
182
300
 
183
301
  test('invalid schema - route', t => {
@@ -185,7 +303,7 @@ test('invalid schema - route', t => {
185
303
 
186
304
  const fastify = Fastify()
187
305
  fastify.route({
188
- handler: () => {},
306
+ handler: () => { },
189
307
  method: 'GET',
190
308
  url: '/invalid',
191
309
  schema: {
@@ -207,7 +325,7 @@ test('same route definition object on multiple prefixes', async t => {
207
325
  t.plan(2)
208
326
 
209
327
  const routeObject = {
210
- handler: () => {},
328
+ handler: () => { },
211
329
  method: 'GET',
212
330
  url: '/simple'
213
331
  }
@@ -1459,7 +1577,7 @@ test('invalid url attribute - non string URL', t => {
1459
1577
  const fastify = Fastify()
1460
1578
 
1461
1579
  try {
1462
- fastify.get(/^\/(donations|skills|blogs)/, () => {})
1580
+ fastify.get(/^\/(donations|skills|blogs)/, () => { })
1463
1581
  } catch (error) {
1464
1582
  t.equal(error.code, FST_ERR_INVALID_URL().code)
1465
1583
  }