@fastify/reply-from 12.0.2 → 12.2.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 (107) hide show
  1. package/.github/workflows/ci.yml +6 -0
  2. package/CLAUDE.md +66 -0
  3. package/LICENSE +4 -1
  4. package/README.md +24 -0
  5. package/index.js +12 -1
  6. package/lib/request.js +16 -6
  7. package/lib/utils.js +1 -0
  8. package/package.json +6 -8
  9. package/test/async-route-handler.test.js +29 -32
  10. package/test/balanced-pool.test.js +48 -0
  11. package/test/base-get.test.js +27 -30
  12. package/test/base-path.test.js +27 -24
  13. package/test/base-querystring.test.js +27 -30
  14. package/test/build-url.test.js +17 -15
  15. package/test/core-with-path-in-base.test.js +30 -33
  16. package/test/custom-undici-instance.test.js +28 -36
  17. package/test/disable-request-logging.test.js +38 -52
  18. package/test/fastify-multipart-incompatibility.test.js +43 -49
  19. package/test/fix-GHSA-v2v2-hph8-q5xp.test.js +3 -2
  20. package/test/full-delete-http2.test.js +12 -11
  21. package/test/full-get-test.test.js +27 -30
  22. package/test/full-https-get.test.js +30 -30
  23. package/test/full-post-extended-content-type.test.js +40 -44
  24. package/test/full-post-http2.test.js +18 -13
  25. package/test/full-post-stream-core.test.js +39 -43
  26. package/test/full-post-stream.test.js +39 -43
  27. package/test/full-post.test.js +36 -38
  28. package/test/full-querystring-rewrite-option-complex.test.js +27 -31
  29. package/test/full-querystring-rewrite-option-function-request.test.js +30 -36
  30. package/test/full-querystring-rewrite-option-function.test.js +30 -33
  31. package/test/full-querystring-rewrite-option.test.js +28 -31
  32. package/test/full-querystring-rewrite-string.test.js +27 -30
  33. package/test/full-querystring-rewrite.test.js +27 -30
  34. package/test/full-querystring.test.js +27 -30
  35. package/test/full-rewrite-body-content-type.test.js +37 -41
  36. package/test/full-rewrite-body-http.test.js +39 -43
  37. package/test/full-rewrite-body-to-empty-string.test.js +37 -41
  38. package/test/full-rewrite-body-to-null.test.js +37 -41
  39. package/test/full-rewrite-body.test.js +39 -43
  40. package/test/get-upstream-cache.test.js +12 -11
  41. package/test/get-upstream-http.test.js +35 -41
  42. package/test/get-upstream-type.test.js +24 -27
  43. package/test/get-upstream-undici.test.js +23 -26
  44. package/test/host-header.test.js +22 -18
  45. package/test/http-agents.test.js +27 -30
  46. package/test/http-global-agent.test.js +20 -33
  47. package/test/http-http2.test.js +13 -18
  48. package/test/http-invalid-target.test.js +13 -17
  49. package/test/http-retry.test.js +22 -29
  50. package/test/http-timeout.test.js +87 -27
  51. package/test/http2-canceled-streams-cleanup.test.js +117 -0
  52. package/test/http2-http2.test.js +8 -8
  53. package/test/http2-https.test.js +29 -27
  54. package/test/http2-invalid-base.test.js +2 -2
  55. package/test/http2-invalid-target.test.js +13 -17
  56. package/test/http2-target-crash.test.js +16 -20
  57. package/test/http2-target-multi-crash.test.js +22 -27
  58. package/test/http2-timeout-disabled.test.js +20 -15
  59. package/test/http2-timeout.test.js +94 -43
  60. package/test/http2-unix-socket.test.js +2 -2
  61. package/test/https-agents.test.js +31 -30
  62. package/test/https-global-agent.test.js +22 -31
  63. package/test/method.test.js +37 -42
  64. package/test/modifyCoreObjects-false.test.js +27 -30
  65. package/test/no-body-opts-with-get.test.js +25 -31
  66. package/test/no-body-opts-with-head.test.js +28 -32
  67. package/test/no-stream-body-option.test.js +34 -36
  68. package/test/on-error.test.js +21 -23
  69. package/test/on-invalid-upstream-response.test.js +30 -37
  70. package/test/onResponse.test.js +25 -32
  71. package/test/padded-body.test.js +38 -43
  72. package/test/post-formbody.test.js +35 -40
  73. package/test/post-plain-text.test.js +35 -39
  74. package/test/post-with-custom-encoded-contenttype.test.js +37 -39
  75. package/test/post-with-octet-stream.test.js +18 -88
  76. package/test/retry-on-503.test.js +27 -26
  77. package/test/retry-with-a-custom-handler.test.js +33 -40
  78. package/test/rewrite-headers-type.test.js +24 -29
  79. package/test/rewrite-headers.test.js +31 -36
  80. package/test/rewrite-request-headers-type.test.js +25 -28
  81. package/test/rewrite-request-headers.test.js +26 -30
  82. package/test/transform-body.test.js +37 -43
  83. package/test/undici-agent.test.js +27 -31
  84. package/test/undici-body.test.js +37 -42
  85. package/test/undici-chaining.test.js +35 -42
  86. package/test/undici-connect-timeout.test.js +13 -13
  87. package/test/undici-custom-dispatcher.test.js +11 -11
  88. package/test/undici-global-agent.test.js +14 -33
  89. package/test/undici-no-destroy.test.js +2 -2
  90. package/test/undici-options.test.js +21 -24
  91. package/test/undici-proxy-agent.test.js +4 -3
  92. package/test/undici-retry.test.js +24 -31
  93. package/test/undici-timeout-body-partial.test.js +14 -16
  94. package/test/undici-timeout-body.test.js +17 -19
  95. package/test/undici-timeout.test.js +86 -23
  96. package/test/undici-with-path-in-base.test.js +28 -31
  97. package/test/undici.test.js +28 -31
  98. package/test/unexpected-error.test.js +13 -18
  99. package/test/unix-http-undici-from.test.js +22 -31
  100. package/test/unix-http-undici.test.js +32 -40
  101. package/test/unix-http.test.js +31 -39
  102. package/test/unix-https-undici.test.js +30 -35
  103. package/test/unix-https.test.js +35 -40
  104. package/types/index.d.ts +13 -5
  105. package/types/index.test-d.ts +6 -6
  106. package/test/get-with-body.test.js +0 -55
  107. package/test/head-with-body.test.js +0 -57
@@ -1,30 +1,30 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
4
  const Fastify = require('fastify')
5
+ const { request, Agent } = require('undici')
5
6
  const From = require('..')
6
- const got = require('got')
7
7
  const FakeTimers = require('@sinonjs/fake-timers')
8
8
 
9
- const clock = FakeTimers.createClock()
10
-
11
9
  test('http request timeout', async (t) => {
10
+ const clock = FakeTimers.createClock()
12
11
  const target = Fastify()
13
- t.teardown(target.close.bind(target))
12
+ t.after(() => target.close())
14
13
 
15
14
  target.get('/', (_request, reply) => {
16
- t.pass('request arrives')
15
+ t.assert.ok('request arrives')
17
16
 
18
- clock.setTimeout(() => {
17
+ setTimeout(() => {
19
18
  reply.status(200).send('hello world')
20
- t.end()
21
19
  }, 200)
20
+
21
+ clock.tick(200)
22
22
  })
23
23
 
24
24
  await target.listen({ port: 0 })
25
25
 
26
26
  const instance = Fastify()
27
- t.teardown(instance.close.bind(instance))
27
+ t.after(() => instance.close())
28
28
 
29
29
  instance.register(From, { http: { requestOptions: { timeout: 100 } } })
30
30
 
@@ -34,30 +34,86 @@ test('http request timeout', async (t) => {
34
34
 
35
35
  await instance.listen({ port: 0 })
36
36
 
37
- try {
38
- await got.get(`http://localhost:${instance.server.address().port}/`, { retry: 0 })
39
- } catch (err) {
40
- t.equal(err.response.statusCode, 504)
41
- t.match(err.response.headers['content-type'], /application\/json/)
42
- t.same(JSON.parse(err.response.body), {
43
- statusCode: 504,
44
- code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
45
- error: 'Gateway Timeout',
46
- message: 'Gateway Timeout'
37
+ const result = await request(`http://localhost:${instance.server.address().port}/`, {
38
+ dispatcher: new Agent({
39
+ pipelining: 0
47
40
  })
41
+ })
42
+
43
+ t.assert.strictEqual(result.statusCode, 504)
44
+ t.assert.match(result.headers['content-type'], /application\/json/)
45
+ t.assert.deepStrictEqual(await result.body.json(), {
46
+ statusCode: 504,
47
+ code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
48
+ error: 'Gateway Timeout',
49
+ message: 'Gateway Timeout'
50
+ })
51
+ clock.tick(200)
52
+ })
53
+
54
+ test('http request with specific timeout', async (t) => {
55
+ const clock = FakeTimers.createClock()
56
+ const target = Fastify()
57
+ t.after(() => target.close())
58
+
59
+ target.get('/', (_request, reply) => {
60
+ t.assert.ok('request arrives')
61
+
62
+ setTimeout(() => {
63
+ reply.status(200).send('hello world')
64
+ }, 200)
65
+
48
66
  clock.tick(200)
49
- return
50
- }
67
+ })
68
+
69
+ await target.listen({ port: 0 })
51
70
 
52
- t.fail()
71
+ const instance = Fastify()
72
+ t.after(() => instance.close())
73
+
74
+ instance.register(From, { http: { requestOptions: { timeout: 100 } } })
75
+
76
+ instance.get('/success', (_request, reply) => {
77
+ reply.from(`http://localhost:${target.server.address().port}/`, {
78
+ timeout: 300
79
+ })
80
+ })
81
+ instance.get('/fail', (_request, reply) => {
82
+ reply.from(`http://localhost:${target.server.address().port}/`, {
83
+ timeout: 50
84
+ })
85
+ })
86
+
87
+ await instance.listen({ port: 0 })
88
+ const result = await request(`http://localhost:${instance.server.address().port}/success`, {
89
+ dispatcher: new Agent({
90
+ pipelining: 0
91
+ })
92
+ })
93
+ t.assert.strictEqual(result.statusCode, 200)
94
+
95
+ const result2 = await request(`http://localhost:${instance.server.address().port}/fail`, {
96
+ dispatcher: new Agent({
97
+ pipelining: 0
98
+ })
99
+ })
100
+
101
+ t.assert.strictEqual(result2.statusCode, 504)
102
+ t.assert.match(result2.headers['content-type'], /application\/json/)
103
+ t.assert.deepStrictEqual(await result2.body.json(), {
104
+ statusCode: 504,
105
+ code: 'FST_REPLY_FROM_GATEWAY_TIMEOUT',
106
+ error: 'Gateway Timeout',
107
+ message: 'Gateway Timeout'
108
+ })
53
109
  })
54
110
 
55
111
  test('http sse removes timeout test', async (t) => {
56
112
  const target = Fastify()
57
- t.teardown(target.close.bind(target))
113
+ t.after(() => target.close())
58
114
 
59
115
  target.get('/', (_request, reply) => {
60
- t.pass('request arrives')
116
+ t.assert.ok('request arrives')
61
117
 
62
118
  reply.header('content-type', 'text/event-stream').status(200).send('hello world')
63
119
  })
@@ -65,7 +121,7 @@ test('http sse removes timeout test', async (t) => {
65
121
  await target.listen({ port: 0 })
66
122
 
67
123
  const instance = Fastify()
68
- t.teardown(instance.close.bind(instance))
124
+ t.after(() => instance.close())
69
125
 
70
126
  instance.register(From, { http: { requestOptions: { timeout: 100 } } })
71
127
 
@@ -75,6 +131,10 @@ test('http sse removes timeout test', async (t) => {
75
131
 
76
132
  await instance.listen({ port: 0 })
77
133
 
78
- const { statusCode } = await got.get(`http://localhost:${instance.server.address().port}/`, { retry: 0 })
79
- t.equal(statusCode, 200)
134
+ const { statusCode } = await request(`http://localhost:${instance.server.address().port}/`, {
135
+ dispatcher: new Agent({
136
+ pipelining: 0
137
+ })
138
+ })
139
+ t.assert.strictEqual(statusCode, 200)
80
140
  })
@@ -0,0 +1,117 @@
1
+ 'use strict'
2
+
3
+ const t = require('node:test')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const fs = require('node:fs')
7
+ const path = require('node:path')
8
+ const http2 = require('node:http2')
9
+ const { once } = require('events')
10
+ const certs = {
11
+ key: fs.readFileSync(path.join(__dirname, 'fixtures', 'fastify.key')),
12
+ cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'fastify.cert'))
13
+ }
14
+ const { HTTP2_HEADER_STATUS, HTTP2_HEADER_PATH } = http2.constants
15
+
16
+ function makeRequest (client, counter) {
17
+ return new Promise((resolve, reject) => {
18
+ const controller = new AbortController()
19
+ const signal = controller.signal
20
+ const cancelRequestEarly = counter % 2 === 0 // cancel early every other request
21
+ let responseCounter = 0
22
+
23
+ const clientStream = client.request({ [HTTP2_HEADER_PATH]: '/' }, { signal })
24
+
25
+ clientStream.end()
26
+
27
+ clientStream.on('data', chunk => {
28
+ const s = chunk.toString()
29
+ // Sometimes we just get NGHTTP2_ENHANCE_YOUR_CALM internal server errors
30
+ if (s.startsWith('{"statusCode":500')) reject(new Error('got internal server error'))
31
+ else responseCounter++
32
+ })
33
+
34
+ clientStream.on('error', err => {
35
+ if (err instanceof Error && err.name === 'AbortError') {
36
+ if (responseCounter === 0 && !cancelRequestEarly) {
37
+ // if we didn´t cancel early we should have received at least one response from the target
38
+ // if not, this indicated the stream resource leak
39
+ reject(new Error('no response'))
40
+ } else resolve()
41
+ } else reject(err instanceof Error ? err : new Error(JSON.stringify(err)))
42
+ })
43
+
44
+ clientStream.on('end', () => { resolve() })
45
+
46
+ setTimeout(() => { controller.abort() }, cancelRequestEarly ? 20 : 200)
47
+ })
48
+ }
49
+
50
+ const httpsOptions = {
51
+ ...certs,
52
+ settings: {
53
+ maxConcurrentStreams: 10, // lower the default so we can reproduce the problem quicker
54
+ }
55
+ }
56
+
57
+ t.test('http2 -> http2', async (t) => {
58
+ const instance = Fastify({
59
+ http2: true,
60
+ https: httpsOptions
61
+ })
62
+
63
+ t.after(() => instance.close())
64
+
65
+ const target = http2.createSecureServer(httpsOptions)
66
+
67
+ target.on('stream', (stream, _headers, _flags) => {
68
+ let counter = 0
69
+ let headerSent = false
70
+
71
+ // deliberately delay sending the headers
72
+ const sendData = () => {
73
+ if (!headerSent) {
74
+ stream.respond({ [HTTP2_HEADER_STATUS]: 200, })
75
+ headerSent = true
76
+ }
77
+ stream.write(counter + '\n')
78
+ counter = counter + 1
79
+ }
80
+
81
+ const intervalId = setInterval(sendData, 50)
82
+
83
+ // ignore write after end errors
84
+ stream.on('error', _err => { })
85
+
86
+ stream.on('close', () => { clearInterval(intervalId) })
87
+ })
88
+
89
+ instance.get('/', (_request, reply) => {
90
+ reply.from()
91
+ })
92
+
93
+ t.after(() => target.close())
94
+
95
+ target.listen()
96
+ await once(target, 'listening')
97
+
98
+ instance.register(From, {
99
+ base: `https://localhost:${target.address().port}`,
100
+ http2: true,
101
+ rejectUnauthorized: false
102
+ })
103
+
104
+ const url = await instance.listen({ port: 0 })
105
+
106
+ const client = http2.connect(url, {
107
+ rejectUnauthorized: false,
108
+ })
109
+
110
+ // see https://github.com/fastify/fastify-reply-from/issues/424
111
+ // without the bug fix this will fail after about 15 requests
112
+ for (let i = 0; i < 30; i++) { await makeRequest(client, i) }
113
+
114
+ client.close()
115
+ instance.close()
116
+ target.close()
117
+ })
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const h2url = require('h2url')
4
- const t = require('tap')
4
+ const t = require('node:test')
5
5
  const Fastify = require('fastify')
6
6
  const From = require('..')
7
7
  const fs = require('node:fs')
@@ -17,14 +17,14 @@ t.test('http2 -> http2', async (t) => {
17
17
  https: certs
18
18
  })
19
19
 
20
- t.teardown(instance.close.bind(instance))
20
+ t.after(() => instance.close())
21
21
 
22
22
  const target = Fastify({
23
23
  http2: true
24
24
  })
25
25
 
26
26
  target.get('/', (_request, reply) => {
27
- t.pass('request proxied')
27
+ t.assert.ok('request proxied')
28
28
  reply.code(404).header('x-my-header', 'hello!').send({
29
29
  hello: 'world'
30
30
  })
@@ -34,7 +34,7 @@ t.test('http2 -> http2', async (t) => {
34
34
  reply.from()
35
35
  })
36
36
 
37
- t.teardown(target.close.bind(target))
37
+ t.after(() => target.close())
38
38
 
39
39
  await target.listen({ port: 0 })
40
40
 
@@ -50,10 +50,10 @@ t.test('http2 -> http2', async (t) => {
50
50
  url: `https://localhost:${instance.server.address().port}`
51
51
  })
52
52
 
53
- t.equal(headers[':status'], 404)
54
- t.equal(headers['x-my-header'], 'hello!')
55
- t.match(headers['content-type'], /application\/json/)
56
- t.same(JSON.parse(body), { hello: 'world' })
53
+ t.assert.strictEqual(headers[':status'], 404)
54
+ t.assert.strictEqual(headers['x-my-header'], 'hello!')
55
+ t.assert.match(headers['content-type'], /application\/json/)
56
+ t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
57
57
  instance.close()
58
58
  target.close()
59
59
  })
@@ -1,10 +1,11 @@
1
1
  'use strict'
2
2
 
3
3
  const h2url = require('h2url')
4
- const t = require('tap')
4
+ const t = require('node:test')
5
+ const assert = require('node:assert')
5
6
  const Fastify = require('fastify')
7
+ const { request, Agent } = require('undici')
6
8
  const From = require('..')
7
- const got = require('got')
8
9
  const fs = require('node:fs')
9
10
  const path = require('node:path')
10
11
  const certs = {
@@ -18,15 +19,12 @@ const instance = Fastify({
18
19
  https: certs
19
20
  })
20
21
 
21
- t.plan(4)
22
- t.teardown(instance.close.bind(instance))
23
-
24
22
  const target = Fastify({
25
23
  https: certs
26
24
  })
27
25
 
28
26
  target.get('/', (_request, reply) => {
29
- t.pass('request proxied')
27
+ assert.ok('request proxied')
30
28
  reply.code(404).header('x-my-header', 'hello!').send({
31
29
  hello: 'world'
32
30
  })
@@ -36,9 +34,7 @@ instance.get('/', (_request, reply) => {
36
34
  reply.from()
37
35
  })
38
36
 
39
- t.teardown(target.close.bind(target))
40
-
41
- async function run () {
37
+ async function run (t) {
42
38
  await target.listen({ port: 0 })
43
39
 
44
40
  instance.register(From, {
@@ -48,33 +44,39 @@ async function run () {
48
44
 
49
45
  await instance.listen({ port: 0 })
50
46
 
51
- t.test('http2 -> https', async (t) => {
47
+ await t.test('http2 -> https', async (t) => {
48
+ t.plan(4)
52
49
  const { headers, body } = await h2url.concat({
53
50
  url: `https://localhost:${instance.server.address().port}`
54
51
  })
55
52
 
56
- t.equal(headers[':status'], 404)
57
- t.equal(headers['x-my-header'], 'hello!')
58
- t.match(headers['content-type'], /application\/json/)
59
- t.same(JSON.parse(body), { hello: 'world' })
53
+ t.assert.strictEqual(headers[':status'], 404)
54
+ t.assert.strictEqual(headers['x-my-header'], 'hello!')
55
+ t.assert.match(headers['content-type'], /application\/json/)
56
+ t.assert.deepStrictEqual(JSON.parse(body), { hello: 'world' })
60
57
  })
61
58
 
62
- t.test('https -> https', async (t) => {
63
- try {
64
- await got(`https://localhost:${instance.server.address().port}`, {
65
- https: {
59
+ await t.test('https -> https', async (t) => {
60
+ t.plan(4)
61
+ const result = await request(`https://localhost:${instance.server.address().port}`, {
62
+ dispatcher: new Agent({
63
+ connect: {
66
64
  rejectUnauthorized: false
67
65
  }
68
66
  })
69
- } catch (err) {
70
- t.equal(err.response.statusCode, 404)
71
- t.equal(err.response.headers['x-my-header'], 'hello!')
72
- t.match(err.response.headers['content-type'], /application\/json/)
73
- t.same(JSON.parse(err.response.body), { hello: 'world' })
74
- return
75
- }
76
- t.fail()
67
+ })
68
+
69
+ t.assert.strictEqual(result.statusCode, 404)
70
+ t.assert.strictEqual(result.headers['x-my-header'], 'hello!')
71
+ t.assert.match(result.headers['content-type'], /application\/json/)
72
+ t.assert.deepStrictEqual(await result.body.json(), { hello: 'world' })
77
73
  })
78
74
  }
79
75
 
80
- run()
76
+ t.test('http2 -> https', async (t) => {
77
+ t.plan(2)
78
+ t.after(() => instance.close())
79
+ t.after(() => target.close())
80
+
81
+ await run(t)
82
+ })
@@ -1,13 +1,13 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
4
  const Fastify = require('fastify')
5
5
  const From = require('../index')
6
6
 
7
7
  test('http2 invalid base', async (t) => {
8
8
  const instance = Fastify()
9
9
 
10
- await t.rejects(async () => instance.register(From, {
10
+ await t.assert.rejects(async () => instance.register(From, {
11
11
  http2: { requestTimeout: 100 }
12
12
  }), new Error('Option base is required when http2 is true'))
13
13
  })
@@ -1,14 +1,14 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
4
  const Fastify = require('fastify')
5
+ const { request } = require('undici')
5
6
  const From = require('..')
6
- const got = require('got')
7
7
 
8
8
  test('http2 invalid target', async (t) => {
9
9
  const instance = Fastify()
10
10
 
11
- t.teardown(instance.close.bind(instance))
11
+ t.after(() => instance.close())
12
12
 
13
13
  instance.get('/', (_request, reply) => {
14
14
  reply.from()
@@ -20,18 +20,14 @@ test('http2 invalid target', async (t) => {
20
20
 
21
21
  await instance.listen({ port: 0 })
22
22
 
23
- try {
24
- await got(`http://localhost:${instance.server.address().port}`)
25
- } catch (err) {
26
- t.equal(err.response.statusCode, 503)
27
- t.match(err.response.headers['content-type'], /application\/json/)
28
- t.same(JSON.parse(err.response.body), {
29
- statusCode: 503,
30
- code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
31
- error: 'Service Unavailable',
32
- message: 'Service Unavailable'
33
- })
34
- return
35
- }
36
- t.fail()
23
+ const result = await request(`http://localhost:${instance.server.address().port}`)
24
+
25
+ t.assert.strictEqual(result.statusCode, 503)
26
+ t.assert.match(result.headers['content-type'], /application\/json/)
27
+ t.assert.deepStrictEqual(await result.body.json(), {
28
+ statusCode: 503,
29
+ code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
30
+ error: 'Service Unavailable',
31
+ message: 'Service Unavailable'
32
+ })
37
33
  })
@@ -1,21 +1,21 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
4
  const Fastify = require('fastify')
5
+ const { request } = require('undici')
5
6
  const From = require('..')
6
- const got = require('got')
7
7
 
8
8
  test('http -> http2 crash', async (t) => {
9
9
  const instance = Fastify()
10
10
 
11
- t.teardown(instance.close.bind(instance))
11
+ t.after(() => instance.close())
12
12
 
13
13
  const target = Fastify({
14
14
  http2: true
15
15
  })
16
16
 
17
17
  target.get('/', (_request, reply) => {
18
- t.pass('request proxied')
18
+ t.assert.ok('request proxied')
19
19
  reply.code(200).send({
20
20
  hello: 'world'
21
21
  })
@@ -25,7 +25,7 @@ test('http -> http2 crash', async (t) => {
25
25
  reply.from()
26
26
  })
27
27
 
28
- t.teardown(target.close.bind(target))
28
+ t.after(() => target.close())
29
29
 
30
30
  await target.listen({ port: 0 })
31
31
 
@@ -36,19 +36,15 @@ test('http -> http2 crash', async (t) => {
36
36
 
37
37
  await instance.listen({ port: 0 })
38
38
 
39
- try {
40
- await target.close()
41
- await got(`http://localhost:${instance.server.address().port}`)
42
- } catch (err) {
43
- t.equal(err.response.statusCode, 503)
44
- t.match(err.response.headers['content-type'], /application\/json/)
45
- t.same(JSON.parse(err.response.body), {
46
- statusCode: 503,
47
- code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
48
- error: 'Service Unavailable',
49
- message: 'Service Unavailable'
50
- })
51
- return
52
- }
53
- t.fail()
39
+ await target.close()
40
+ const result = await request(`http://localhost:${instance.server.address().port}`)
41
+
42
+ t.assert.strictEqual(result.statusCode, 503)
43
+ t.assert.match(result.headers['content-type'], /application\/json/)
44
+ t.assert.deepStrictEqual(await result.body.json(), {
45
+ statusCode: 503,
46
+ code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
47
+ error: 'Service Unavailable',
48
+ message: 'Service Unavailable'
49
+ })
54
50
  })
@@ -1,14 +1,14 @@
1
1
  'use strict'
2
2
 
3
- const { test } = require('tap')
3
+ const { test } = require('node:test')
4
4
  const Fastify = require('fastify')
5
+ const { request } = require('undici')
5
6
  const From = require('..')
6
- const got = require('got')
7
7
 
8
8
  test('http -> http2 crash multiple times', async (t) => {
9
9
  const instance = Fastify()
10
10
 
11
- t.teardown(instance.close.bind(instance))
11
+ t.after(() => instance.close())
12
12
 
13
13
  instance.get('/', (_request, reply) => {
14
14
  reply.from()
@@ -23,29 +23,24 @@ test('http -> http2 crash multiple times', async (t) => {
23
23
  })
24
24
 
25
25
  await instance.listen({ port: 0 })
26
-
27
- try {
28
- let target = setupTarget()
29
- await target.listen({ port: 3128 })
30
- await got(`http://localhost:${instance.server.address().port}`)
31
- await target.close()
32
- target = setupTarget()
33
- await target.listen({ port: 3128 })
34
- await got(`http://localhost:${instance.server.address().port}`)
35
- await target.close()
36
- await got(`http://localhost:${instance.server.address().port}`)
37
- } catch (err) {
38
- t.equal(err.response.statusCode, 503)
39
- t.match(err.response.headers['content-type'], /application\/json/)
40
- t.same(JSON.parse(err.response.body), {
41
- statusCode: 503,
42
- code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
43
- error: 'Service Unavailable',
44
- message: 'Service Unavailable'
45
- })
46
- return
47
- }
48
- t.fail()
26
+ let target = setupTarget()
27
+ await target.listen({ port: 3128 })
28
+ await request(`http://localhost:${instance.server.address().port}`)
29
+ await target.close()
30
+ target = setupTarget()
31
+ await target.listen({ port: 3128 })
32
+ await request(`http://localhost:${instance.server.address().port}`)
33
+ await target.close()
34
+ const result = await request(`http://localhost:${instance.server.address().port}`)
35
+
36
+ t.assert.strictEqual(result.statusCode, 503)
37
+ t.assert.match(result.headers['content-type'], /application\/json/)
38
+ t.assert.deepStrictEqual(await result.body.json(), {
39
+ statusCode: 503,
40
+ code: 'FST_REPLY_FROM_SERVICE_UNAVAILABLE',
41
+ error: 'Service Unavailable',
42
+ message: 'Service Unavailable'
43
+ })
49
44
 
50
45
  function setupTarget () {
51
46
  const target = Fastify({
@@ -53,7 +48,7 @@ test('http -> http2 crash multiple times', async (t) => {
53
48
  })
54
49
 
55
50
  target.get('/', (request, reply) => {
56
- t.pass('request proxied')
51
+ t.assert.ok('request proxied')
57
52
  reply.code(200).send({
58
53
  hello: 'world'
59
54
  })