@fastify/reply-from 12.1.0 → 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 +3 -0
  2. package/CLAUDE.md +66 -0
  3. package/LICENSE +4 -1
  4. package/README.md +20 -0
  5. package/index.js +10 -0
  6. package/lib/request.js +11 -2
  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 +49 -42
  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 +58 -65
  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 +41 -37
  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 +9 -2
  105. package/types/index.test-d.ts +3 -4
  106. package/test/get-with-body.test.js +0 -55
  107. package/test/head-with-body.test.js +0 -57
@@ -1,17 +1,12 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const t = require('node:test')
4
4
  const Fastify = require('fastify')
5
+ const { request } = require('undici')
5
6
  const From = require('..')
6
7
  const fs = require('node:fs')
7
8
  const querystring = require('node:querystring')
8
9
  const http = require('node:http')
9
- const get = require('simple-get').concat
10
-
11
- if (process.platform === 'win32') {
12
- t.pass()
13
- process.exit(0)
14
- }
15
10
 
16
11
  const socketPath = `${__filename}.socket`
17
12
  const upstream = `unix+http://${querystring.escape(socketPath)}/`
@@ -24,42 +19,39 @@ instance.register(From, {
24
19
  base: upstream
25
20
  })
26
21
 
27
- t.plan(10)
28
- t.teardown(instance.close.bind(instance))
29
-
30
- try {
31
- fs.unlinkSync(socketPath)
32
- } catch (_) {
33
- }
22
+ t.test('unix http', { skip: process.platform === 'win32' }, async (t) => {
23
+ t.plan(7)
24
+ t.after(() => instance.close())
25
+
26
+ try {
27
+ fs.unlinkSync(socketPath)
28
+ } catch (_) {
29
+ }
30
+
31
+ const target = http.createServer((req, res) => {
32
+ t.assert.ok('request proxied')
33
+ t.assert.strictEqual(req.method, 'GET')
34
+ t.assert.strictEqual(req.url, '/hello')
35
+ res.statusCode = 205
36
+ res.setHeader('Content-Type', 'text/plain')
37
+ res.setHeader('x-my-header', 'hello!')
38
+ res.end('hello world')
39
+ })
34
40
 
35
- const target = http.createServer((req, res) => {
36
- t.pass('request proxied')
37
- t.equal(req.method, 'GET')
38
- t.equal(req.url, '/hello')
39
- res.statusCode = 205
40
- res.setHeader('Content-Type', 'text/plain')
41
- res.setHeader('x-my-header', 'hello!')
42
- res.end('hello world')
43
- })
41
+ instance.get('/', (_request, reply) => {
42
+ reply.from('hello')
43
+ })
44
44
 
45
- instance.get('/', (_request, reply) => {
46
- reply.from('hello')
47
- })
45
+ t.after(() => target.close())
48
46
 
49
- t.teardown(target.close.bind(target))
47
+ await instance.listen({ port: 0 })
50
48
 
51
- instance.listen({ port: 0 }, (err) => {
52
- t.error(err)
49
+ await new Promise(resolve => target.listen(socketPath, resolve))
53
50
 
54
- target.listen(socketPath, (err) => {
55
- t.error(err)
51
+ const result = await request(`http://localhost:${instance.server.address().port}`)
56
52
 
57
- get(`http://localhost:${instance.server.address().port}`, (err, res, data) => {
58
- t.error(err)
59
- t.equal(res.headers['content-type'], 'text/plain')
60
- t.equal(res.headers['x-my-header'], 'hello!')
61
- t.equal(res.statusCode, 205)
62
- t.equal(data.toString(), 'hello world')
63
- })
64
- })
53
+ t.assert.strictEqual(result.headers['content-type'], 'text/plain')
54
+ t.assert.strictEqual(result.headers['x-my-header'], 'hello!')
55
+ t.assert.strictEqual(result.statusCode, 205)
56
+ t.assert.strictEqual(await result.body.text(), 'hello world')
65
57
  })
@@ -1,11 +1,11 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const t = require('node:test')
4
4
  const Fastify = require('fastify')
5
5
  const From = require('..')
6
6
  const https = require('node:https')
7
- const get = require('simple-get').concat
8
7
  const fs = require('node:fs')
8
+ const { request, Agent } = require('undici')
9
9
  const querystring = require('node:querystring')
10
10
  const path = require('node:path')
11
11
  const certs = {
@@ -13,11 +13,6 @@ const certs = {
13
13
  cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'fastify.cert'))
14
14
  }
15
15
 
16
- if (process.platform === 'win32') {
17
- t.pass()
18
- process.exit(0)
19
- }
20
-
21
16
  const socketPath = `${__filename}.socket`
22
17
 
23
18
  try {
@@ -32,40 +27,40 @@ instance.register(From, {
32
27
  base: `unix+https://${querystring.escape(socketPath)}`
33
28
  })
34
29
 
35
- t.plan(10)
36
- t.teardown(instance.close.bind(instance))
30
+ t.test('unix https undici', { skip: process.platform === 'win32' }, async (t) => {
31
+ t.plan(7)
32
+ t.after(() => instance.close())
37
33
 
38
- const target = https.createServer(certs, (req, res) => {
39
- t.pass('request proxied')
40
- t.equal(req.method, 'GET')
41
- t.equal(req.url, '/hello')
42
- res.statusCode = 205
43
- res.setHeader('Content-Type', 'text/plain')
44
- res.setHeader('x-my-header', 'hello!')
45
- res.end('hello world')
46
- })
34
+ const target = https.createServer(certs, (req, res) => {
35
+ t.assert.ok('request proxied')
36
+ t.assert.strictEqual(req.method, 'GET')
37
+ t.assert.strictEqual(req.url, '/hello')
38
+ res.statusCode = 205
39
+ res.setHeader('Content-Type', 'text/plain')
40
+ res.setHeader('x-my-header', 'hello!')
41
+ res.end('hello world')
42
+ })
47
43
 
48
- instance.get('/', (_request, reply) => {
49
- reply.from('hello')
50
- })
44
+ instance.get('/', (_request, reply) => {
45
+ reply.from('hello')
46
+ })
51
47
 
52
- t.teardown(target.close.bind(target))
48
+ t.after(() => target.close())
53
49
 
54
- instance.listen({ port: 0 }, (err) => {
55
- t.error(err)
50
+ await instance.listen({ port: 0 })
56
51
 
57
- target.listen(socketPath, (err) => {
58
- t.error(err)
52
+ await new Promise(resolve => target.listen(socketPath, resolve))
59
53
 
60
- get({
61
- url: `https://localhost:${instance.server.address().port}`,
62
- rejectUnauthorized: false
63
- }, (err, res, data) => {
64
- t.error(err)
65
- t.equal(res.headers['content-type'], 'text/plain')
66
- t.equal(res.headers['x-my-header'], 'hello!')
67
- t.equal(res.statusCode, 205)
68
- t.equal(data.toString(), 'hello world')
54
+ const result = await request(`https://localhost:${instance.server.address().port}`, {
55
+ dispatcher: new Agent({
56
+ connect: {
57
+ rejectUnauthorized: false
58
+ }
69
59
  })
70
60
  })
61
+
62
+ t.assert.strictEqual(result.headers['content-type'], 'text/plain')
63
+ t.assert.strictEqual(result.headers['x-my-header'], 'hello!')
64
+ t.assert.strictEqual(result.statusCode, 205)
65
+ t.assert.strictEqual(await result.body.text(), 'hello world')
71
66
  })
@@ -1,10 +1,10 @@
1
1
  'use strict'
2
2
 
3
- const t = require('tap')
3
+ const t = require('node:test')
4
4
  const Fastify = require('fastify')
5
5
  const From = require('..')
6
6
  const https = require('node:https')
7
- const get = require('simple-get').concat
7
+ const { request, Agent } = require('undici')
8
8
  const fs = require('node:fs')
9
9
  const querystring = require('node:querystring')
10
10
  const path = require('node:path')
@@ -13,11 +13,6 @@ const certs = {
13
13
  cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'fastify.cert'))
14
14
  }
15
15
 
16
- if (process.platform === 'win32') {
17
- t.pass()
18
- process.exit(0)
19
- }
20
-
21
16
  const instance = Fastify({
22
17
  https: certs
23
18
  })
@@ -25,47 +20,47 @@ instance.register(From, {
25
20
  http: true
26
21
  })
27
22
 
28
- t.plan(10)
29
- t.teardown(instance.close.bind(instance))
23
+ t.test('unix https', { skip: process.platform === 'win32' }, async (t) => {
24
+ t.plan(7)
25
+ t.after(() => instance.close())
30
26
 
31
- const socketPath = `${__filename}.socket`
27
+ const socketPath = `${__filename}.socket`
32
28
 
33
- try {
34
- fs.unlinkSync(socketPath)
35
- } catch (_) {
36
- }
29
+ try {
30
+ fs.unlinkSync(socketPath)
31
+ } catch (_) {
32
+ }
37
33
 
38
- const target = https.createServer(certs, (req, res) => {
39
- t.pass('request proxied')
40
- t.equal(req.method, 'GET')
41
- t.equal(req.url, '/hello')
42
- res.statusCode = 205
43
- res.setHeader('Content-Type', 'text/plain')
44
- res.setHeader('x-my-header', 'hello!')
45
- res.end('hello world')
46
- })
34
+ const target = https.createServer(certs, (req, res) => {
35
+ t.assert.ok('request proxied')
36
+ t.assert.strictEqual(req.method, 'GET')
37
+ t.assert.strictEqual(req.url, '/hello')
38
+ res.statusCode = 205
39
+ res.setHeader('Content-Type', 'text/plain')
40
+ res.setHeader('x-my-header', 'hello!')
41
+ res.end('hello world')
42
+ })
47
43
 
48
- instance.get('/', (_request, reply) => {
49
- reply.from(`unix+https://${querystring.escape(socketPath)}/hello`)
50
- })
44
+ instance.get('/', (_request, reply) => {
45
+ reply.from(`unix+https://${querystring.escape(socketPath)}/hello`)
46
+ })
51
47
 
52
- t.teardown(target.close.bind(target))
48
+ t.after(() => target.close())
53
49
 
54
- instance.listen({ port: 0 }, (err) => {
55
- t.error(err)
50
+ await instance.listen({ port: 0 })
56
51
 
57
- target.listen(socketPath, (err) => {
58
- t.error(err)
52
+ await new Promise(resolve => target.listen(socketPath, resolve))
59
53
 
60
- get({
61
- url: `https://localhost:${instance.server.address().port}`,
62
- rejectUnauthorized: false
63
- }, (err, res, data) => {
64
- t.error(err)
65
- t.equal(res.headers['content-type'], 'text/plain')
66
- t.equal(res.headers['x-my-header'], 'hello!')
67
- t.equal(res.statusCode, 205)
68
- t.equal(data.toString(), 'hello world')
54
+ const result = await request(`https://localhost:${instance.server.address().port}`, {
55
+ dispatcher: new Agent({
56
+ connect: {
57
+ rejectUnauthorized: false
58
+ }
69
59
  })
70
60
  })
61
+
62
+ t.assert.strictEqual(result.headers['content-type'], 'text/plain')
63
+ t.assert.strictEqual(result.headers['x-my-header'], 'hello!')
64
+ t.assert.strictEqual(result.statusCode, 205)
65
+ t.assert.strictEqual(await result.body.text(), 'hello world')
71
66
  })
package/types/index.d.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  Agent,
16
16
  AgentOptions,
17
17
  IncomingHttpHeaders,
18
+ IncomingMessage,
18
19
  RequestOptions,
19
20
  } from 'node:http'
20
21
  import {
@@ -55,6 +56,11 @@ declare namespace fastifyReplyFrom {
55
56
  retriesCount: number;
56
57
  getDefaultDelay: () => number | null;
57
58
  }
59
+
60
+ export type RawServerResponse<T extends RawServerBase> = RawReplyDefaultExpression<T> & {
61
+ stream: IncomingMessage
62
+ }
63
+
58
64
  export interface FastifyReplyFromHooks {
59
65
  queryString?: { [key: string]: unknown } | QueryStringFunction;
60
66
  contentType?: string;
@@ -63,7 +69,7 @@ declare namespace fastifyReplyFrom {
63
69
  onResponse?: (
64
70
  request: FastifyRequest<RequestGenericInterface, RawServerBase>,
65
71
  reply: FastifyReply<RouteGenericInterface, RawServerBase>,
66
- res: RawReplyDefaultExpression<RawServerBase>
72
+ res: RawServerResponse<RawServerBase>
67
73
  ) => void;
68
74
  onError?: (
69
75
  reply: FastifyReply<RouteGenericInterface, RawServerBase>,
@@ -100,12 +106,13 @@ declare namespace fastifyReplyFrom {
100
106
  }
101
107
 
102
108
  export interface FastifyReplyFromOptions {
103
- base?: string;
109
+ base?: string | string[];
104
110
  cacheURLs?: number;
105
111
  disableCache?: boolean;
106
112
  http?: HttpOptions;
107
113
  http2?: Http2Options | boolean;
108
114
  undici?: Pool.Options & { proxy?: string | URL | ProxyAgent.Options } | { request: Dispatcher['request'] };
115
+ balancedPoolOptions?: Pool.Options & Record<string, unknown>;
109
116
  contentTypesToEncode?: string[];
110
117
  retryMethods?: (HTTPMethods | 'TRACE')[];
111
118
  maxRetriesOn503?: number;
@@ -1,11 +1,11 @@
1
- import fastify, { FastifyReply, FastifyRequest, RawReplyDefaultExpression, RawServerBase, RequestGenericInterface, RouteGenericInterface } from 'fastify'
1
+ import fastify, { FastifyReply, FastifyRequest, RawServerBase, RequestGenericInterface, RouteGenericInterface } from 'fastify'
2
2
  import * as http from 'node:http'
3
3
  import { IncomingHttpHeaders } from 'node:http2'
4
4
  import * as https from 'node:https'
5
5
  import { AddressInfo } from 'node:net'
6
6
  import { expectType } from 'tsd'
7
7
  import { Agent, Client, Dispatcher, Pool } from 'undici'
8
- import replyFrom, { FastifyReplyFromOptions } from '..'
8
+ import replyFrom, { FastifyReplyFromOptions, RawServerResponse } from '..'
9
9
  // @ts-ignore
10
10
  import tap from 'tap'
11
11
 
@@ -83,7 +83,7 @@ async function main () {
83
83
  onResponse (request, reply, res) {
84
84
  expectType<FastifyRequest<RequestGenericInterface, RawServerBase>>(request)
85
85
  expectType<FastifyReply<RouteGenericInterface, RawServerBase>>(reply)
86
- expectType<RawReplyDefaultExpression<RawServerBase>>(res)
86
+ expectType<RawServerResponse<RawServerBase>>(res)
87
87
  expectType<number>(res.statusCode)
88
88
  }
89
89
  })
@@ -103,7 +103,6 @@ async function main () {
103
103
  instance.get('/http2', (_request, reply) => {
104
104
  reply.from('/', {
105
105
  method: 'POST',
106
-
107
106
  retryDelay: ({ req, res, getDefaultDelay }) => {
108
107
  const defaultDelay = getDefaultDelay()
109
108
  if (defaultDelay) return defaultDelay
@@ -1,55 +0,0 @@
1
- 'use strict'
2
-
3
- const t = require('tap')
4
- const Fastify = require('fastify')
5
- const From = require('..')
6
- const http = require('node:http')
7
- const get = require('simple-get').concat
8
-
9
- const instance = Fastify()
10
-
11
- t.plan(11)
12
- t.teardown(instance.close.bind(instance))
13
-
14
- const target = http.createServer((req, res) => {
15
- t.pass('request proxied')
16
- t.equal(req.method, 'GET')
17
- t.equal(req.url, '/')
18
- t.equal(req.body, undefined)
19
- res.statusCode = 205
20
- res.setHeader('Content-Type', 'text/plain')
21
- res.setHeader('x-my-header', 'hello!')
22
- res.end('hello world')
23
- })
24
-
25
- instance.get('/', (_request, reply) => {
26
- reply.from()
27
- })
28
-
29
- t.teardown(target.close.bind(target))
30
-
31
- target.listen({ port: 0 }, (err) => {
32
- t.error(err)
33
-
34
- instance.register(From, {
35
- base: `http://localhost:${target.address().port}`,
36
- // Use node core HTTP, Undici requires spec compliance
37
- http: {}
38
- })
39
-
40
- instance.listen({ port: 0 }, (err) => {
41
- t.error(err)
42
-
43
- get({
44
- url: `http://localhost:${instance.server.address().port}`,
45
- method: 'GET',
46
- body: 'this is get body'
47
- }, (err, res, data) => {
48
- t.error(err)
49
- t.equal(res.headers['content-type'], 'text/plain')
50
- t.equal(res.headers['x-my-header'], 'hello!')
51
- t.equal(res.statusCode, 205)
52
- t.equal(data.toString(), 'hello world')
53
- })
54
- })
55
- })
@@ -1,57 +0,0 @@
1
- 'use strict'
2
-
3
- const t = require('tap')
4
- const Fastify = require('fastify')
5
- const From = require('..')
6
- const http = require('node:http')
7
- const get = require('simple-get').concat
8
-
9
- const instance = Fastify()
10
-
11
- t.plan(13)
12
- t.teardown(instance.close.bind(instance))
13
-
14
- const target = http.createServer((req, res) => {
15
- t.pass('request proxied')
16
- t.equal(req.method, 'HEAD')
17
- t.equal(req.url, '/')
18
- t.equal(req.headers['content-length'], '16')
19
- t.equal(req.body, undefined)
20
- res.statusCode = 205
21
- res.setHeader('Content-Type', 'text/plain')
22
- res.setHeader('x-my-header', 'hello!')
23
- res.end('hello world')
24
- })
25
-
26
- instance.head('/', (_request, reply) => {
27
- t.pass('head received')
28
- reply.from()
29
- })
30
-
31
- t.teardown(target.close.bind(target))
32
-
33
- target.listen({ port: 0 }, (err) => {
34
- t.error(err)
35
-
36
- instance.register(From, {
37
- base: `http://localhost:${target.address().port}`,
38
- // Use node core HTTP, Undici requires spec compliance
39
- http: {}
40
- })
41
-
42
- instance.listen({ port: 0 }, (err) => {
43
- t.error(err)
44
-
45
- get({
46
- url: `http://localhost:${instance.server.address().port}`,
47
- method: 'HEAD',
48
- body: 'this is get body'
49
- }, (err, res, data) => {
50
- t.error(err)
51
- t.equal(res.headers['content-type'], 'text/plain')
52
- t.equal(res.headers['x-my-header'], 'hello!')
53
- t.equal(res.statusCode, 205)
54
- t.equal(data.toString(), '')
55
- })
56
- })
57
- })