fastify 3.24.0 → 3.25.2
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.
- package/README.md +30 -29
- package/docs/{Benchmarking.md → Guides/Benchmarking.md} +14 -5
- package/docs/Guides/Ecosystem.md +513 -0
- package/docs/{Fluent-Schema.md → Guides/Fluent-Schema.md} +16 -7
- package/docs/{Getting-Started.md → Guides/Getting-Started.md} +180 -60
- package/docs/Guides/Index.md +30 -4
- package/docs/{Migration-Guide-V3.md → Guides/Migration-Guide-V3.md} +43 -37
- package/docs/{Plugins-Guide.md → Guides/Plugins-Guide.md} +196 -82
- package/docs/{Recommendations.md → Guides/Recommendations.md} +17 -10
- package/docs/{Serverless.md → Guides/Serverless.md} +200 -42
- package/docs/Guides/Style-Guide.md +246 -0
- package/docs/{Testing.md → Guides/Testing.md} +26 -12
- package/docs/Guides/Write-Plugin.md +102 -0
- package/docs/{ContentTypeParser.md → Reference/ContentTypeParser.md} +68 -30
- package/docs/{Decorators.md → Reference/Decorators.md} +52 -47
- package/docs/{Encapsulation.md → Reference/Encapsulation.md} +3 -3
- package/docs/{Errors.md → Reference/Errors.md} +77 -47
- package/docs/{HTTP2.md → Reference/HTTP2.md} +13 -13
- package/docs/{Hooks.md → Reference/Hooks.md} +157 -70
- package/docs/Reference/Index.md +71 -0
- package/docs/{LTS.md → Reference/LTS.md} +31 -32
- package/docs/{Lifecycle.md → Reference/Lifecycle.md} +15 -7
- package/docs/{Logging.md → Reference/Logging.md} +68 -28
- package/docs/Reference/Middleware.md +78 -0
- package/docs/{Plugins.md → Reference/Plugins.md} +91 -34
- package/docs/{Reply.md → Reference/Reply.md} +205 -94
- package/docs/{Request.md → Reference/Request.md} +32 -16
- package/docs/{Routes.md → Reference/Routes.md} +243 -113
- package/docs/{Server.md → Reference/Server.md} +516 -267
- package/docs/{TypeScript.md → Reference/TypeScript.md} +451 -191
- package/docs/{Validation-and-Serialization.md → Reference/Validation-and-Serialization.md} +178 -86
- package/docs/index.md +24 -0
- package/examples/typescript-server.ts +1 -1
- package/fastify.js +2 -3
- package/lib/contentTypeParser.js +11 -6
- package/lib/decorate.js +6 -3
- package/lib/logger.js +1 -1
- package/lib/route.js +1 -1
- package/lib/server.js +9 -8
- package/package.json +9 -4
- package/test/als.test.js +74 -0
- package/test/constrained-routes.test.js +220 -0
- package/test/custom-parser.test.js +11 -2
- package/test/decorator.test.js +38 -0
- package/test/handler-context.test.js +11 -4
- package/test/http2/closing.test.js +14 -5
- package/test/http2/constraint.test.js +91 -0
- package/test/listen.test.js +36 -22
- package/test/logger.test.js +16 -0
- package/test/maxRequestsPerSocket.test.js +10 -0
- package/test/request-error.test.js +2 -8
- package/test/requestTimeout.test.js +4 -1
- package/test/router-options.test.js +10 -1
- package/test/schema-feature.test.js +146 -0
- package/test/stream.test.js +14 -3
- package/test/trust-proxy.test.js +15 -7
- package/test/types/instance.test-d.ts +52 -1
- package/test/types/request.test-d.ts +7 -1
- package/test/types/route.test-d.ts +21 -0
- package/types/hooks.d.ts +12 -1
- package/types/instance.d.ts +16 -6
- package/types/request.d.ts +4 -1
- package/types/route.d.ts +1 -1
- package/docs/Ecosystem.md +0 -211
- package/docs/Middleware.md +0 -53
- package/docs/Style-Guide.md +0 -185
- package/docs/Write-Plugin.md +0 -58
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.2",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -108,6 +108,11 @@
|
|
|
108
108
|
"name": "Vincent Le Goff",
|
|
109
109
|
"email": "vince.legoff@gmail.com",
|
|
110
110
|
"url": "https://github.com/zekth"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "Luis Orbaiceta",
|
|
114
|
+
"email": "luisorbaiceta@gmail.com",
|
|
115
|
+
"url": "https://luisorbaiceta.com"
|
|
111
116
|
}
|
|
112
117
|
],
|
|
113
118
|
"license": "MIT",
|
|
@@ -163,10 +168,10 @@
|
|
|
163
168
|
"snazzy": "^9.0.0",
|
|
164
169
|
"split2": "^4.1.0",
|
|
165
170
|
"standard": "^16.0.1",
|
|
166
|
-
"tap": "^15.
|
|
171
|
+
"tap": "^15.1.1",
|
|
167
172
|
"tap-mocha-reporter": "^5.0.1",
|
|
168
173
|
"then-sleep": "^1.0.1",
|
|
169
|
-
"tsd": "^0.
|
|
174
|
+
"tsd": "^0.19.0",
|
|
170
175
|
"typescript": "^4.0.2",
|
|
171
176
|
"undici": "^3.3.5",
|
|
172
177
|
"x-xss-protection": "^2.0.0",
|
|
@@ -179,7 +184,7 @@
|
|
|
179
184
|
"fast-json-stringify": "^2.5.2",
|
|
180
185
|
"fastify-error": "^0.3.0",
|
|
181
186
|
"fastify-warning": "^0.2.0",
|
|
182
|
-
"find-my-way": "^4.
|
|
187
|
+
"find-my-way": "^4.5.0",
|
|
183
188
|
"flatstr": "^1.0.12",
|
|
184
189
|
"light-my-request": "^4.2.0",
|
|
185
190
|
"pino": "^6.13.0",
|
package/test/als.test.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { AsyncLocalStorage } = require('async_hooks')
|
|
4
|
+
const t = require('tap')
|
|
5
|
+
const Fastify = require('..')
|
|
6
|
+
const sget = require('simple-get').concat
|
|
7
|
+
|
|
8
|
+
if (!AsyncLocalStorage) {
|
|
9
|
+
t.skip('AsyncLocalStorage not available, skipping test')
|
|
10
|
+
process.exit(0)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const storage = new AsyncLocalStorage()
|
|
14
|
+
const app = Fastify({ logger: false })
|
|
15
|
+
|
|
16
|
+
let counter = 0
|
|
17
|
+
app.addHook('onRequest', (req, reply, next) => {
|
|
18
|
+
const id = counter++
|
|
19
|
+
storage.run({ id }, next)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
app.get('/', function (request, reply) {
|
|
23
|
+
t.ok(storage.getStore())
|
|
24
|
+
const id = storage.getStore().id
|
|
25
|
+
reply.send({ id })
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
app.post('/', function (request, reply) {
|
|
29
|
+
t.ok(storage.getStore())
|
|
30
|
+
const id = storage.getStore().id
|
|
31
|
+
reply.send({ id })
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
app.listen(3000, function (err, address) {
|
|
35
|
+
t.error(err)
|
|
36
|
+
|
|
37
|
+
sget({
|
|
38
|
+
method: 'POST',
|
|
39
|
+
url: 'http://localhost:' + app.server.address().port,
|
|
40
|
+
body: {
|
|
41
|
+
hello: 'world'
|
|
42
|
+
},
|
|
43
|
+
json: true
|
|
44
|
+
}, (err, response, body) => {
|
|
45
|
+
t.error(err)
|
|
46
|
+
t.equal(response.statusCode, 200)
|
|
47
|
+
t.same(body, { id: 0 })
|
|
48
|
+
|
|
49
|
+
sget({
|
|
50
|
+
method: 'POST',
|
|
51
|
+
url: 'http://localhost:' + app.server.address().port,
|
|
52
|
+
body: {
|
|
53
|
+
hello: 'world'
|
|
54
|
+
},
|
|
55
|
+
json: true
|
|
56
|
+
}, (err, response, body) => {
|
|
57
|
+
t.error(err)
|
|
58
|
+
t.equal(response.statusCode, 200)
|
|
59
|
+
t.same(body, { id: 1 })
|
|
60
|
+
|
|
61
|
+
sget({
|
|
62
|
+
method: 'GET',
|
|
63
|
+
url: 'http://localhost:' + app.server.address().port,
|
|
64
|
+
json: true
|
|
65
|
+
}, (err, response, body) => {
|
|
66
|
+
t.error(err)
|
|
67
|
+
t.equal(response.statusCode, 200)
|
|
68
|
+
t.same(body, { id: 2 })
|
|
69
|
+
app.close()
|
|
70
|
+
t.end()
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
})
|
|
@@ -182,3 +182,223 @@ test('Should allow registering custom constrained routes', t => {
|
|
|
182
182
|
t.equal(res.statusCode, 404)
|
|
183
183
|
})
|
|
184
184
|
})
|
|
185
|
+
|
|
186
|
+
test('Should allow registering an unconstrained route after a constrained route', t => {
|
|
187
|
+
t.plan(6)
|
|
188
|
+
const fastify = Fastify()
|
|
189
|
+
|
|
190
|
+
fastify.route({
|
|
191
|
+
method: 'GET',
|
|
192
|
+
url: '/',
|
|
193
|
+
constraints: { host: 'fastify.io' },
|
|
194
|
+
handler: (req, reply) => {
|
|
195
|
+
reply.send({ hello: 'from fastify.io' })
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
fastify.route({
|
|
200
|
+
method: 'GET',
|
|
201
|
+
url: '/',
|
|
202
|
+
handler: (req, reply) => {
|
|
203
|
+
reply.send({ hello: 'from any other domain' })
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
fastify.inject({
|
|
208
|
+
method: 'GET',
|
|
209
|
+
url: '/',
|
|
210
|
+
headers: {
|
|
211
|
+
host: 'fastify.io'
|
|
212
|
+
}
|
|
213
|
+
}, (err, res) => {
|
|
214
|
+
t.error(err)
|
|
215
|
+
t.same(JSON.parse(res.payload), { hello: 'from fastify.io' })
|
|
216
|
+
t.equal(res.statusCode, 200)
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
fastify.inject({
|
|
220
|
+
method: 'GET',
|
|
221
|
+
url: '/',
|
|
222
|
+
headers: {
|
|
223
|
+
host: 'example.com'
|
|
224
|
+
}
|
|
225
|
+
}, (err, res) => {
|
|
226
|
+
t.error(err)
|
|
227
|
+
t.same(JSON.parse(res.payload), { hello: 'from any other domain' })
|
|
228
|
+
t.equal(res.statusCode, 200)
|
|
229
|
+
})
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
test('Should allow registering constrained routes in a prefixed plugin', t => {
|
|
233
|
+
t.plan(3)
|
|
234
|
+
|
|
235
|
+
const fastify = Fastify()
|
|
236
|
+
|
|
237
|
+
fastify.register(async (scope, opts) => {
|
|
238
|
+
scope.route({
|
|
239
|
+
method: 'GET',
|
|
240
|
+
constraints: { host: 'fastify.io' },
|
|
241
|
+
path: '/route',
|
|
242
|
+
handler: (req, reply) => {
|
|
243
|
+
reply.send({ ok: true })
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
}, { prefix: '/prefix' })
|
|
247
|
+
|
|
248
|
+
fastify.inject({
|
|
249
|
+
method: 'GET',
|
|
250
|
+
url: '/prefix/route',
|
|
251
|
+
headers: {
|
|
252
|
+
host: 'fastify.io'
|
|
253
|
+
}
|
|
254
|
+
}, (err, res) => {
|
|
255
|
+
t.error(err)
|
|
256
|
+
t.same(JSON.parse(res.payload), { ok: true })
|
|
257
|
+
t.equal(res.statusCode, 200)
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test('Should allow registering a constrained GET route after a constrained HEAD route', t => {
|
|
262
|
+
t.plan(3)
|
|
263
|
+
const fastify = Fastify()
|
|
264
|
+
|
|
265
|
+
fastify.route({
|
|
266
|
+
method: 'HEAD',
|
|
267
|
+
url: '/',
|
|
268
|
+
constraints: { host: 'fastify.io' },
|
|
269
|
+
handler: (req, reply) => {
|
|
270
|
+
reply.header('content-type', 'text/plain')
|
|
271
|
+
reply.send('custom HEAD response')
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
fastify.route({
|
|
276
|
+
method: 'GET',
|
|
277
|
+
url: '/',
|
|
278
|
+
constraints: { host: 'fastify.io' },
|
|
279
|
+
handler: (req, reply) => {
|
|
280
|
+
reply.send({ hello: 'from any other domain' })
|
|
281
|
+
}
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
fastify.inject({
|
|
285
|
+
method: 'HEAD',
|
|
286
|
+
url: '/',
|
|
287
|
+
headers: {
|
|
288
|
+
host: 'fastify.io'
|
|
289
|
+
}
|
|
290
|
+
}, (err, res) => {
|
|
291
|
+
t.error(err)
|
|
292
|
+
t.same(res.payload, 'custom HEAD response')
|
|
293
|
+
t.equal(res.statusCode, 200)
|
|
294
|
+
})
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
test('Should allow registering a constrained GET route after an unconstrained HEAD route', t => {
|
|
298
|
+
t.plan(3)
|
|
299
|
+
const fastify = Fastify()
|
|
300
|
+
|
|
301
|
+
fastify.route({
|
|
302
|
+
method: 'HEAD',
|
|
303
|
+
url: '/',
|
|
304
|
+
handler: (req, reply) => {
|
|
305
|
+
reply.header('content-type', 'text/plain')
|
|
306
|
+
reply.send('custom HEAD response')
|
|
307
|
+
}
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
fastify.route({
|
|
311
|
+
method: 'GET',
|
|
312
|
+
url: '/',
|
|
313
|
+
constraints: { host: 'fastify.io' },
|
|
314
|
+
handler: (req, reply) => {
|
|
315
|
+
reply.send({ hello: 'from any other domain' })
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
fastify.inject({
|
|
320
|
+
method: 'HEAD',
|
|
321
|
+
url: '/',
|
|
322
|
+
headers: {
|
|
323
|
+
host: 'fastify.io'
|
|
324
|
+
}
|
|
325
|
+
}, (err, res) => {
|
|
326
|
+
t.error(err)
|
|
327
|
+
t.same(res.payload, 'custom HEAD response')
|
|
328
|
+
t.equal(res.statusCode, 200)
|
|
329
|
+
})
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
test('Will not try to re-createprefixed HEAD route if it already exists and exposeHeadRoutes is true for constrained routes', async (t) => {
|
|
333
|
+
t.plan(1)
|
|
334
|
+
|
|
335
|
+
const fastify = Fastify({ exposeHeadRoutes: true })
|
|
336
|
+
|
|
337
|
+
fastify.register((scope, opts, next) => {
|
|
338
|
+
scope.route({
|
|
339
|
+
method: 'HEAD',
|
|
340
|
+
path: '/route',
|
|
341
|
+
constraints: { host: 'fastify.io' },
|
|
342
|
+
handler: (req, reply) => {
|
|
343
|
+
reply.header('content-type', 'text/plain')
|
|
344
|
+
reply.send('custom HEAD response')
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
scope.route({
|
|
348
|
+
method: 'GET',
|
|
349
|
+
path: '/route',
|
|
350
|
+
constraints: { host: 'fastify.io' },
|
|
351
|
+
handler: (req, reply) => {
|
|
352
|
+
reply.send({ ok: true })
|
|
353
|
+
}
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
next()
|
|
357
|
+
}, { prefix: '/prefix' })
|
|
358
|
+
|
|
359
|
+
await fastify.ready()
|
|
360
|
+
|
|
361
|
+
t.ok(true)
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
test('allows separate constrained and unconstrained HEAD routes', async (t) => {
|
|
365
|
+
t.plan(1)
|
|
366
|
+
|
|
367
|
+
const fastify = Fastify({ exposeHeadRoutes: true })
|
|
368
|
+
|
|
369
|
+
fastify.register((scope, opts, next) => {
|
|
370
|
+
scope.route({
|
|
371
|
+
method: 'HEAD',
|
|
372
|
+
path: '/route',
|
|
373
|
+
handler: (req, reply) => {
|
|
374
|
+
reply.header('content-type', 'text/plain')
|
|
375
|
+
reply.send('unconstrained HEAD response')
|
|
376
|
+
}
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
scope.route({
|
|
380
|
+
method: 'HEAD',
|
|
381
|
+
path: '/route',
|
|
382
|
+
constraints: { host: 'fastify.io' },
|
|
383
|
+
handler: (req, reply) => {
|
|
384
|
+
reply.header('content-type', 'text/plain')
|
|
385
|
+
reply.send('constrained HEAD response')
|
|
386
|
+
}
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
scope.route({
|
|
390
|
+
method: 'GET',
|
|
391
|
+
path: '/route',
|
|
392
|
+
constraints: { host: 'fastify.io' },
|
|
393
|
+
handler: (req, reply) => {
|
|
394
|
+
reply.send({ ok: true })
|
|
395
|
+
}
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
next()
|
|
399
|
+
}, { prefix: '/prefix' })
|
|
400
|
+
|
|
401
|
+
await fastify.ready()
|
|
402
|
+
|
|
403
|
+
t.ok(true)
|
|
404
|
+
})
|
|
@@ -25,6 +25,15 @@ function plainTextParser (request, callback) {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
function getUrl (app) {
|
|
29
|
+
const { address, port } = app.server.address()
|
|
30
|
+
if (address === '::1') {
|
|
31
|
+
return `http://[${address}]:${port}`
|
|
32
|
+
} else {
|
|
33
|
+
return `http://${address}:${port}`
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
28
37
|
process.removeAllListeners('warning')
|
|
29
38
|
|
|
30
39
|
test('contentTypeParser method should exist', t => {
|
|
@@ -61,7 +70,7 @@ test('contentTypeParser should add a custom parser', t => {
|
|
|
61
70
|
|
|
62
71
|
sget({
|
|
63
72
|
method: 'POST',
|
|
64
|
-
url:
|
|
73
|
+
url: getUrl(fastify),
|
|
65
74
|
body: '{"hello":"world"}',
|
|
66
75
|
headers: {
|
|
67
76
|
'Content-Type': 'application/jsoff'
|
|
@@ -78,7 +87,7 @@ test('contentTypeParser should add a custom parser', t => {
|
|
|
78
87
|
|
|
79
88
|
sget({
|
|
80
89
|
method: 'OPTIONS',
|
|
81
|
-
url:
|
|
90
|
+
url: getUrl(fastify),
|
|
82
91
|
body: '{"hello":"world"}',
|
|
83
92
|
headers: {
|
|
84
93
|
'Content-Type': 'application/jsoff'
|
package/test/decorator.test.js
CHANGED
|
@@ -1024,3 +1024,41 @@ test('decorateRequest/decorateReply is not set to a value', t => {
|
|
|
1024
1024
|
})
|
|
1025
1025
|
})
|
|
1026
1026
|
})
|
|
1027
|
+
|
|
1028
|
+
test('decorateRequest with dependencies', (t) => {
|
|
1029
|
+
t.plan(2)
|
|
1030
|
+
const app = Fastify()
|
|
1031
|
+
|
|
1032
|
+
const decorator1 = 'bar'
|
|
1033
|
+
const decorator2 = 'foo'
|
|
1034
|
+
|
|
1035
|
+
app.decorate('decorator1', decorator1)
|
|
1036
|
+
app.decorateRequest('decorator1', decorator1)
|
|
1037
|
+
|
|
1038
|
+
if (
|
|
1039
|
+
app.hasDecorator('decorator1') &&
|
|
1040
|
+
app.hasRequestDecorator('decorator1')
|
|
1041
|
+
) {
|
|
1042
|
+
t.doesNotThrow(() => app.decorateRequest('decorator2', decorator2, ['decorator1']))
|
|
1043
|
+
t.ok(app.hasRequestDecorator('decorator2'))
|
|
1044
|
+
}
|
|
1045
|
+
})
|
|
1046
|
+
|
|
1047
|
+
test('decorateRequest with dependencies (functions)', (t) => {
|
|
1048
|
+
t.plan(2)
|
|
1049
|
+
const app = Fastify()
|
|
1050
|
+
|
|
1051
|
+
const decorator1 = () => 'bar'
|
|
1052
|
+
const decorator2 = () => 'foo'
|
|
1053
|
+
|
|
1054
|
+
app.decorate('decorator1', decorator1)
|
|
1055
|
+
app.decorateRequest('decorator1', decorator1)
|
|
1056
|
+
|
|
1057
|
+
if (
|
|
1058
|
+
app.hasDecorator('decorator1') &&
|
|
1059
|
+
app.hasRequestDecorator('decorator1')
|
|
1060
|
+
) {
|
|
1061
|
+
t.doesNotThrow(() => app.decorateRequest('decorator2', decorator2, ['decorator1']))
|
|
1062
|
+
t.ok(app.hasRequestDecorator('decorator2'))
|
|
1063
|
+
}
|
|
1064
|
+
})
|
|
@@ -4,6 +4,15 @@ const http = require('http')
|
|
|
4
4
|
const test = require('tap').test
|
|
5
5
|
const fastify = require('../')
|
|
6
6
|
|
|
7
|
+
function getUrl (app) {
|
|
8
|
+
const { address, port } = app.server.address()
|
|
9
|
+
if (address === '::1') {
|
|
10
|
+
return `http://[${address}]:${port}`
|
|
11
|
+
} else {
|
|
12
|
+
return `http://${address}:${port}`
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
test('handlers receive correct `this` context', (t) => {
|
|
8
17
|
t.plan(4)
|
|
9
18
|
|
|
@@ -29,8 +38,7 @@ test('handlers receive correct `this` context', (t) => {
|
|
|
29
38
|
t.ok(instance.foo)
|
|
30
39
|
t.equal(instance.foo, 'foo')
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
http.get(address, () => {}).on('error', t.threw)
|
|
41
|
+
http.get(getUrl(instance), () => {}).on('error', t.threw)
|
|
34
42
|
})
|
|
35
43
|
})
|
|
36
44
|
|
|
@@ -50,7 +58,6 @@ test('handlers have access to the internal context', (t) => {
|
|
|
50
58
|
instance.listen(0, (err) => {
|
|
51
59
|
instance.server.unref()
|
|
52
60
|
if (err) t.threw(err)
|
|
53
|
-
|
|
54
|
-
http.get(address, () => {}).on('error', t.threw)
|
|
61
|
+
http.get(getUrl(instance), () => {}).on('error', t.threw)
|
|
55
62
|
})
|
|
56
63
|
})
|
|
@@ -11,6 +11,15 @@ const { once } = require('events')
|
|
|
11
11
|
const { buildCertificate } = require('../build-certificate')
|
|
12
12
|
t.before(buildCertificate)
|
|
13
13
|
|
|
14
|
+
function getUrl (app) {
|
|
15
|
+
const { address, port } = app.server.address()
|
|
16
|
+
if (address === '::1') {
|
|
17
|
+
return `http://[${address}]:${port}`
|
|
18
|
+
} else {
|
|
19
|
+
return `http://${address}:${port}`
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
14
23
|
t.test('http/2 request while fastify closing', t => {
|
|
15
24
|
let fastify
|
|
16
25
|
try {
|
|
@@ -30,7 +39,7 @@ t.test('http/2 request while fastify closing', t => {
|
|
|
30
39
|
|
|
31
40
|
// Skipped because there is likely a bug on Node 8.
|
|
32
41
|
t.test('return 200', { skip: semver.lt(process.versions.node, '10.15.0') }, t => {
|
|
33
|
-
const url =
|
|
42
|
+
const url = getUrl(fastify)
|
|
34
43
|
const session = http2.connect(url, function () {
|
|
35
44
|
this.request({
|
|
36
45
|
':method': 'GET',
|
|
@@ -78,7 +87,7 @@ t.test('http/2 request while fastify closing - return503OnClosing: false', t =>
|
|
|
78
87
|
|
|
79
88
|
// Skipped because there is likely a bug on Node 8.
|
|
80
89
|
t.test('return 200', { skip: semver.lt(process.versions.node, '10.15.0') }, t => {
|
|
81
|
-
const url =
|
|
90
|
+
const url = getUrl(fastify)
|
|
82
91
|
const session = http2.connect(url, function () {
|
|
83
92
|
this.request({
|
|
84
93
|
':method': 'GET',
|
|
@@ -115,7 +124,7 @@ t.test('http/2 closes successfully with async await', { skip: semver.lt(process.
|
|
|
115
124
|
|
|
116
125
|
await fastify.listen(0)
|
|
117
126
|
|
|
118
|
-
const url =
|
|
127
|
+
const url = getUrl(fastify)
|
|
119
128
|
const session = await connect(url)
|
|
120
129
|
// An error might or might not happen, as it's OS dependent.
|
|
121
130
|
session.on('error', () => {})
|
|
@@ -135,7 +144,7 @@ t.test('https/2 closes successfully with async await', { skip: semver.lt(process
|
|
|
135
144
|
|
|
136
145
|
await fastify.listen(0)
|
|
137
146
|
|
|
138
|
-
const url =
|
|
147
|
+
const url = getUrl(fastify)
|
|
139
148
|
const session = await connect(url)
|
|
140
149
|
// An error might or might not happen, as it's OS dependent.
|
|
141
150
|
session.on('error', () => {})
|
|
@@ -159,7 +168,7 @@ t.test('http/2 server side session emits a timeout event', { skip: semver.lt(pro
|
|
|
159
168
|
|
|
160
169
|
await fastify.listen(0)
|
|
161
170
|
|
|
162
|
-
const url =
|
|
171
|
+
const url = getUrl(fastify)
|
|
163
172
|
const session = await connect(url)
|
|
164
173
|
const req = session.request({
|
|
165
174
|
':method': 'GET',
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const Fastify = require('../..')
|
|
6
|
+
const h2url = require('h2url')
|
|
7
|
+
|
|
8
|
+
const alpha = { res: 'alpha' }
|
|
9
|
+
const beta = { res: 'beta' }
|
|
10
|
+
|
|
11
|
+
const { buildCertificate } = require('../build-certificate')
|
|
12
|
+
t.before(buildCertificate)
|
|
13
|
+
|
|
14
|
+
test('A route supports host constraints under http2 protocol and secure connection', (t) => {
|
|
15
|
+
t.plan(5)
|
|
16
|
+
|
|
17
|
+
let fastify
|
|
18
|
+
try {
|
|
19
|
+
fastify = Fastify({
|
|
20
|
+
http2: true,
|
|
21
|
+
https: {
|
|
22
|
+
key: global.context.key,
|
|
23
|
+
cert: global.context.cert
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
t.pass('Key/cert successfully loaded')
|
|
27
|
+
} catch (e) {
|
|
28
|
+
t.fail('Key/cert loading failed', e)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const constrain = 'fastify.io'
|
|
32
|
+
|
|
33
|
+
fastify.route({
|
|
34
|
+
method: 'GET',
|
|
35
|
+
url: '/',
|
|
36
|
+
handler: function (_, reply) {
|
|
37
|
+
reply.code(200).send(alpha)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
fastify.route({
|
|
41
|
+
method: 'GET',
|
|
42
|
+
url: '/beta',
|
|
43
|
+
constraints: { host: constrain },
|
|
44
|
+
handler: function (_, reply) {
|
|
45
|
+
reply.code(200).send(beta)
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
fastify.listen(0, err => {
|
|
50
|
+
t.error(err)
|
|
51
|
+
fastify.server.unref()
|
|
52
|
+
|
|
53
|
+
t.test('https get request - no constrain', async (t) => {
|
|
54
|
+
t.plan(3)
|
|
55
|
+
|
|
56
|
+
const url = `https://localhost:${fastify.server.address().port}`
|
|
57
|
+
const res = await h2url.concat({ url })
|
|
58
|
+
|
|
59
|
+
t.equal(res.headers[':status'], 200)
|
|
60
|
+
t.equal(res.headers['content-length'], '' + JSON.stringify(alpha).length)
|
|
61
|
+
t.same(JSON.parse(res.body), alpha)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
t.test('https get request - constrain', async (t) => {
|
|
65
|
+
t.plan(3)
|
|
66
|
+
|
|
67
|
+
const url = `https://localhost:${fastify.server.address().port}/beta`
|
|
68
|
+
const res = await h2url.concat({
|
|
69
|
+
url,
|
|
70
|
+
headers: {
|
|
71
|
+
':authority': constrain
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
t.equal(res.headers[':status'], 200)
|
|
76
|
+
t.equal(res.headers['content-length'], '' + JSON.stringify(beta).length)
|
|
77
|
+
t.same(JSON.parse(res.body), beta)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
t.test('https get request - constrain - not found', async (t) => {
|
|
81
|
+
t.plan(1)
|
|
82
|
+
|
|
83
|
+
const url = `https://localhost:${fastify.server.address().port}/beta`
|
|
84
|
+
const res = await h2url.concat({
|
|
85
|
+
url
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
t.equal(res.headers[':status'], 404)
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
})
|