@fastify/reply-from 7.0.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 (88) hide show
  1. package/.github/dependabot.yml +13 -0
  2. package/.github/stale.yml +21 -0
  3. package/.github/workflows/ci.yml +60 -0
  4. package/.taprc +5 -0
  5. package/LICENSE +21 -0
  6. package/README.md +335 -0
  7. package/example.js +36 -0
  8. package/index.d.ts +99 -0
  9. package/index.js +262 -0
  10. package/lib/request.js +288 -0
  11. package/lib/utils.js +81 -0
  12. package/package.json +70 -0
  13. package/test/async-route-handler.js +50 -0
  14. package/test/base-get.js +48 -0
  15. package/test/base-path.js +38 -0
  16. package/test/base-querystring.js +48 -0
  17. package/test/build-url.js +69 -0
  18. package/test/core-with-path-in-base.js +50 -0
  19. package/test/custom-undici-instance.js +77 -0
  20. package/test/fastify-multipart-incompatibility.js +90 -0
  21. package/test/fixtures/fastify.cert +19 -0
  22. package/test/fixtures/fastify.key +27 -0
  23. package/test/fixtures/file.txt +1 -0
  24. package/test/full-get.js +45 -0
  25. package/test/full-https-get.js +55 -0
  26. package/test/full-post-extended-content-type.js +59 -0
  27. package/test/full-post-http2.js +49 -0
  28. package/test/full-post-stream-core.js +66 -0
  29. package/test/full-post-stream.js +64 -0
  30. package/test/full-post.js +56 -0
  31. package/test/full-querystring-rewrite-option-complex.js +48 -0
  32. package/test/full-querystring-rewrite-option-function.js +51 -0
  33. package/test/full-querystring-rewrite-option.js +48 -0
  34. package/test/full-querystring-rewrite-string.js +46 -0
  35. package/test/full-querystring-rewrite.js +46 -0
  36. package/test/full-querystring.js +46 -0
  37. package/test/full-rewrite-body-content-type.js +59 -0
  38. package/test/full-rewrite-body-http.js +63 -0
  39. package/test/full-rewrite-body-to-empty-string.js +61 -0
  40. package/test/full-rewrite-body-to-null.js +61 -0
  41. package/test/full-rewrite-body.js +61 -0
  42. package/test/get-upstream-http.js +70 -0
  43. package/test/get-upstream-undici.js +45 -0
  44. package/test/get-with-body.js +55 -0
  45. package/test/head-with-body.js +57 -0
  46. package/test/host-header.js +67 -0
  47. package/test/http-agents.js +55 -0
  48. package/test/http-http2.js +50 -0
  49. package/test/http-invalid-target.js +35 -0
  50. package/test/http-retry.js +109 -0
  51. package/test/http-timeout.js +56 -0
  52. package/test/http2-http2.js +57 -0
  53. package/test/http2-https.js +80 -0
  54. package/test/http2-invalid-target.js +36 -0
  55. package/test/http2-target-crash.js +53 -0
  56. package/test/http2-target-multi-crash.js +60 -0
  57. package/test/http2-timeout.js +92 -0
  58. package/test/https-agents.js +67 -0
  59. package/test/index.test-d.ts +136 -0
  60. package/test/modifyCoreObjects-false.js +48 -0
  61. package/test/no-body-opts-with-get.js +49 -0
  62. package/test/no-body-opts-with-head.js +51 -0
  63. package/test/no-stream-body-option.js +58 -0
  64. package/test/on-error.js +62 -0
  65. package/test/onResponse.js +48 -0
  66. package/test/padded-body.js +64 -0
  67. package/test/post-formbody.js +59 -0
  68. package/test/post-plain-text.js +56 -0
  69. package/test/post-with-custom-encoded-contenttype.js +65 -0
  70. package/test/retry-on-503.js +101 -0
  71. package/test/rewrite-headers.js +52 -0
  72. package/test/rewrite-request-headers.js +47 -0
  73. package/test/transform-body.js +61 -0
  74. package/test/undici-agent.js +77 -0
  75. package/test/undici-body.js +70 -0
  76. package/test/undici-options.js +73 -0
  77. package/test/undici-retry.js +109 -0
  78. package/test/undici-timeout-body-partial.js +60 -0
  79. package/test/undici-timeout-body.js +63 -0
  80. package/test/undici-timeout.js +61 -0
  81. package/test/undici-with-path-in-base.js +50 -0
  82. package/test/undici.js +50 -0
  83. package/test/unexpected-error.js +46 -0
  84. package/test/unix-http-undici-from.js +51 -0
  85. package/test/unix-http-undici.js +62 -0
  86. package/test/unix-http.js +65 -0
  87. package/test/unix-https-undici.js +71 -0
  88. package/test/unix-https.js +71 -0
@@ -0,0 +1,136 @@
1
+ import replyFrom, { FastifyReplyFromOptions } from "../";
2
+ import fastify, {FastifyReply, RawServerBase} from "fastify";
3
+ import { AddressInfo } from "net";
4
+ import { IncomingHttpHeaders } from "http2";
5
+ import { expectType } from 'tsd';
6
+ import * as http from 'http';
7
+ import * as https from 'https';
8
+ import * as http2 from 'http2';
9
+ // @ts-ignore
10
+ import tap from 'tap'
11
+
12
+ const fullOptions: FastifyReplyFromOptions = {
13
+ base: "http://example2.com",
14
+ http: {
15
+ agentOptions: {
16
+ keepAliveMsecs: 60 * 1000,
17
+ maxFreeSockets: 2048,
18
+ maxSockets: 2048
19
+ },
20
+ requestOptions: {
21
+ timeout: 1000
22
+ },
23
+ agents: {
24
+ 'http:': new http.Agent({}),
25
+ 'https:': new https.Agent({})
26
+ }
27
+ },
28
+ http2: {
29
+ sessionTimeout: 1000,
30
+ requestTimeout: 1000,
31
+ sessionOptions: {
32
+ rejectUnauthorized: true
33
+ },
34
+ requestOptions: {
35
+ endStream: true
36
+ }
37
+ },
38
+ cacheURLs: 100,
39
+ disableCache: false,
40
+ undici: {
41
+ connections: 100,
42
+ pipelining: 10
43
+ },
44
+ contentTypesToEncode: ['application/x-www-form-urlencoded'],
45
+ retryMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'],
46
+ maxRetriesOn503: 10,
47
+ };
48
+ tap.autoend(false);
49
+
50
+ async function main() {
51
+ const server = fastify();
52
+
53
+ server.register(replyFrom);
54
+
55
+ server.register(replyFrom, {});
56
+
57
+ server.register(replyFrom, {http2: true});
58
+
59
+ server.register(replyFrom, fullOptions);
60
+
61
+ server.get("/v1", (request, reply) => {
62
+ reply.from();
63
+ });
64
+ server.get("/v3", (request, reply) => {
65
+ reply.from("/v3", {
66
+ body: {hello: "world"},
67
+ rewriteRequestHeaders(req, headers) {
68
+ expectType<http.IncomingMessage | http2.Http2ServerRequest>(req);
69
+ return headers;
70
+ },
71
+ getUpstream(req, base) {
72
+ expectType<http.IncomingMessage | http2.Http2ServerRequest>(req);
73
+ return base;
74
+ }
75
+ });
76
+ });
77
+
78
+ // http2
79
+ const instance = fastify({http2: true});
80
+ // @ts-ignore
81
+ tap.tearDown(instance.close.bind(instance));
82
+ const target = fastify({http2: true});
83
+ // @ts-ignore
84
+ tap.tearDown(target.close.bind(target));
85
+ instance.get("/", (request, reply) => {
86
+ reply.from();
87
+ });
88
+
89
+ instance.get("/http2", (request, reply) => {
90
+ reply.from("/", {
91
+ rewriteHeaders(headers, req) {
92
+ return headers;
93
+ },
94
+ rewriteRequestHeaders(req, headers: IncomingHttpHeaders) {
95
+ return headers;
96
+ },
97
+ getUpstream(req, base) {
98
+ return base;
99
+ },
100
+ onError(reply: FastifyReply<RawServerBase>, error) {
101
+ return reply.send(error.error);
102
+ }
103
+ });
104
+ });
105
+
106
+ await target.listen(0);
107
+ const port = (target.server.address() as AddressInfo).port;
108
+ instance.register(replyFrom, {
109
+ base: `http://localhost:${port}`,
110
+ http2: {
111
+ sessionOptions: {
112
+ rejectUnauthorized: false,
113
+ },
114
+ },
115
+ });
116
+ instance.register(replyFrom, {
117
+ base: `http://localhost:${port}`,
118
+ http2: true,
119
+ });
120
+ await instance.listen(0);
121
+
122
+ const undiciInstance = fastify();
123
+ undiciInstance.register(replyFrom, {
124
+ base: "http://example2.com",
125
+ undici: {
126
+ pipelining: 10,
127
+ connections: 10
128
+ }
129
+ });
130
+ await undiciInstance.ready();
131
+
132
+ tap.pass('done');
133
+ tap.end();
134
+ }
135
+
136
+ main();
@@ -0,0 +1,48 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+
9
+ const instance = Fastify({ modifyCoreObjects: false })
10
+
11
+ t.plan(10)
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
+ res.statusCode = 205
19
+ res.setHeader('Content-Type', 'text/plain')
20
+ res.setHeader('x-my-header', 'hello!')
21
+ res.end('hello world')
22
+ })
23
+
24
+ instance.get('/', (request, reply) => {
25
+ reply.from()
26
+ })
27
+
28
+ t.teardown(target.close.bind(target))
29
+
30
+ target.listen(0, (err) => {
31
+ t.error(err)
32
+
33
+ instance.register(From, {
34
+ base: `http://localhost:${target.address().port}`
35
+ })
36
+
37
+ instance.listen(0, (err) => {
38
+ t.error(err)
39
+
40
+ get(`http://localhost:${instance.server.address().port}`, (err, res, data) => {
41
+ t.error(err)
42
+ t.equal(res.headers['content-type'], 'text/plain')
43
+ t.equal(res.headers['x-my-header'], 'hello!')
44
+ t.equal(res.statusCode, 205)
45
+ t.equal(data.toString(), 'hello world')
46
+ })
47
+ })
48
+ })
@@ -0,0 +1,49 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+
9
+ const instance = Fastify()
10
+
11
+ t.plan(6)
12
+ t.teardown(instance.close.bind(instance))
13
+
14
+ const target = http.createServer((req, res) => {
15
+ t.fail('this should never get called')
16
+ res.end('hello world')
17
+ })
18
+
19
+ instance.get('/', (request, reply) => {
20
+ try {
21
+ reply.from(null, { body: 'this is the new body' })
22
+ } catch (e) {
23
+ t.equal(e.message, 'Rewriting the body when doing a GET is not allowed')
24
+ reply.send('hello world')
25
+ }
26
+ })
27
+
28
+ t.teardown(target.close.bind(target))
29
+
30
+ target.listen(0, (err) => {
31
+ t.error(err)
32
+
33
+ instance.register(From, {
34
+ base: `http://localhost:${target.address().port}`
35
+ })
36
+
37
+ instance.listen(0, (err) => {
38
+ t.error(err)
39
+
40
+ get({
41
+ url: `http://localhost:${instance.server.address().port}`,
42
+ method: 'GET'
43
+ }, (err, res, data) => {
44
+ t.error(err)
45
+ t.equal(res.statusCode, 200)
46
+ t.equal(data.toString(), 'hello world')
47
+ })
48
+ })
49
+ })
@@ -0,0 +1,51 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+
9
+ const instance = Fastify()
10
+
11
+ t.plan(7)
12
+ t.teardown(instance.close.bind(instance))
13
+
14
+ const target = http.createServer((req, res) => {
15
+ t.fail('this should never get called')
16
+ res.end('hello world')
17
+ })
18
+
19
+ instance.head('/', (request, reply) => {
20
+ try {
21
+ reply.from(null, { body: 'this is the new body' })
22
+ } catch (e) {
23
+ t.equal(e.message, 'Rewriting the body when doing a HEAD is not allowed')
24
+ reply.header('x-http-error', '1')
25
+ reply.send('hello world')
26
+ }
27
+ })
28
+
29
+ t.teardown(target.close.bind(target))
30
+
31
+ target.listen(0, (err) => {
32
+ t.error(err)
33
+
34
+ instance.register(From, {
35
+ base: `http://localhost:${target.address().port}`
36
+ })
37
+
38
+ instance.listen(0, (err) => {
39
+ t.error(err)
40
+
41
+ get({
42
+ url: `http://localhost:${instance.server.address().port}`,
43
+ method: 'HEAD'
44
+ }, (err, res, data) => {
45
+ t.error(err)
46
+ t.equal(res.statusCode, 200)
47
+ t.equal(res.headers['x-http-error'], '1')
48
+ t.equal(data.toString(), '')
49
+ })
50
+ })
51
+ })
@@ -0,0 +1,58 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+ const Readable = require('stream').Readable
9
+
10
+ const instance = Fastify()
11
+ instance.register(From)
12
+
13
+ t.plan(5)
14
+ t.teardown(instance.close.bind(instance))
15
+
16
+ const target = http.createServer((req, res) => {
17
+ t.fail('the target server should never be called')
18
+ res.end()
19
+ })
20
+
21
+ instance.post('/', (request, reply) => {
22
+ const body = new Readable({
23
+ read: function () {
24
+ t.fail('the read function should never be called')
25
+ }
26
+ })
27
+
28
+ t.throws(() => {
29
+ reply.from(`http://localhost:${target.address().port}`, {
30
+ body
31
+ })
32
+ })
33
+
34
+ // return a 500
35
+ reply.code(500).send({ an: 'error' })
36
+ })
37
+
38
+ t.teardown(target.close.bind(target))
39
+
40
+ instance.listen(0, (err) => {
41
+ t.error(err)
42
+
43
+ target.listen(0, (err) => {
44
+ t.error(err)
45
+
46
+ get({
47
+ url: `http://localhost:${instance.server.address().port}`,
48
+ method: 'POST',
49
+ json: true,
50
+ body: {
51
+ hello: 'world'
52
+ }
53
+ }, (err, res) => {
54
+ t.error(err)
55
+ t.equal(res.statusCode, 500)
56
+ })
57
+ })
58
+ })
@@ -0,0 +1,62 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const got = require('got')
7
+ const FakeTimers = require('@sinonjs/fake-timers')
8
+
9
+ const clock = FakeTimers.createClock()
10
+
11
+ t.autoend(false)
12
+
13
+ const target = Fastify()
14
+ t.teardown(target.close.bind(target))
15
+
16
+ target.get('/', (request, reply) => {
17
+ t.pass('request arrives')
18
+
19
+ clock.setTimeout(() => {
20
+ reply.status(200).send('hello world')
21
+ t.end()
22
+ }, 1000)
23
+ })
24
+
25
+ async function main () {
26
+ await target.listen(0)
27
+
28
+ const instance = Fastify()
29
+ t.teardown(instance.close.bind(instance))
30
+
31
+ instance.register(From, { http: { requestOptions: { timeout: 100 } } })
32
+
33
+ instance.get('/', (request, reply) => {
34
+ reply.from(`http://localhost:${target.server.address().port}/`,
35
+ {
36
+ onError: (reply, { error }) => {
37
+ t.equal(error.status, 504)
38
+ reply.code(error.status).send(error)
39
+ }
40
+ })
41
+ })
42
+
43
+ await instance.listen(0)
44
+
45
+ try {
46
+ await got.get(`http://localhost:${instance.server.address().port}/`, { retry: 0 })
47
+ } catch (err) {
48
+ t.equal(err.response.statusCode, 504)
49
+ t.match(err.response.headers['content-type'], /application\/json/)
50
+ t.same(JSON.parse(err.response.body), {
51
+ statusCode: 504,
52
+ error: 'Gateway Timeout',
53
+ message: 'Gateway Timeout'
54
+ })
55
+ clock.tick(1000)
56
+ return
57
+ }
58
+
59
+ t.fail()
60
+ }
61
+
62
+ main()
@@ -0,0 +1,48 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+
9
+ const instance = Fastify()
10
+ instance.register(From)
11
+
12
+ t.plan(8)
13
+ t.teardown(instance.close.bind(instance))
14
+
15
+ const target = http.createServer((req, res) => {
16
+ t.pass('request proxied')
17
+ t.equal(req.method, 'GET')
18
+ res.statusCode = 200
19
+ res.end('hello world')
20
+ })
21
+
22
+ instance.get('/', (request1, reply) => {
23
+ reply.from(`http://localhost:${target.address().port}`, {
24
+ onResponse: (request2, reply, res) => {
25
+ t.equal(request1.raw, request2.raw)
26
+ reply.send(res)
27
+ }
28
+ })
29
+ })
30
+
31
+ t.teardown(target.close.bind(target))
32
+
33
+ instance.listen(0, (err) => {
34
+ t.error(err)
35
+
36
+ target.listen(0, (err) => {
37
+ t.error(err)
38
+
39
+ get(
40
+ `http://localhost:${instance.server.address().port}`,
41
+ (err, res, data) => {
42
+ t.error(err)
43
+ t.equal(res.statusCode, 200)
44
+ t.equal(data.toString(), 'hello world')
45
+ }
46
+ )
47
+ })
48
+ })
@@ -0,0 +1,64 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+
9
+ const instance = Fastify()
10
+ instance.register(From)
11
+
12
+ t.plan(9)
13
+ t.teardown(instance.close.bind(instance))
14
+
15
+ const bodyString = `{
16
+ "hello": "world"
17
+ }`
18
+
19
+ const parsedLength = Buffer.byteLength(JSON.stringify(JSON.parse(bodyString)))
20
+
21
+ const target = http.createServer((req, res) => {
22
+ t.pass('request proxied')
23
+ t.equal(req.method, 'POST')
24
+ t.equal(req.headers['content-type'], 'application/json')
25
+ t.same(req.headers['content-length'], parsedLength)
26
+ let data = ''
27
+ req.setEncoding('utf8')
28
+ req.on('data', (d) => {
29
+ data += d
30
+ })
31
+ req.on('end', () => {
32
+ t.same(JSON.parse(data), { hello: 'world' })
33
+ res.statusCode = 200
34
+ res.setHeader('content-type', 'application/json')
35
+ res.end(JSON.stringify({ something: 'else' }))
36
+ })
37
+ })
38
+
39
+ instance.post('/', (request, reply) => {
40
+ reply.from(`http://localhost:${target.address().port}`)
41
+ })
42
+
43
+ t.teardown(target.close.bind(target))
44
+
45
+ instance.listen(0, (err) => {
46
+ t.error(err)
47
+
48
+ target.listen(0, (err) => {
49
+ t.error(err)
50
+
51
+ get({
52
+ url: `http://localhost:${instance.server.address().port}`,
53
+ method: 'POST',
54
+ headers: {
55
+ 'content-type': 'application/json'
56
+ },
57
+ body: bodyString
58
+ }, (err, res, data) => {
59
+ t.error(err)
60
+ const parsed = JSON.parse(data)
61
+ t.same(parsed, { something: 'else' })
62
+ })
63
+ })
64
+ })
@@ -0,0 +1,59 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+
9
+ const instance = Fastify()
10
+ instance.register(From, {
11
+ contentTypesToEncode: ['application/x-www-form-urlencoded']
12
+ })
13
+ instance.register(require('fastify-formbody'))
14
+
15
+ t.plan(9)
16
+ t.teardown(instance.close.bind(instance))
17
+
18
+ const target = http.createServer((req, res) => {
19
+ t.pass('request proxied')
20
+ t.equal(req.method, 'POST')
21
+ t.equal(req.headers['content-type'], 'application/x-www-form-urlencoded')
22
+ let data = ''
23
+ req.setEncoding('utf8')
24
+ req.on('data', (d) => {
25
+ data += d
26
+ })
27
+ req.on('end', () => {
28
+ const str = data.toString()
29
+ t.same(JSON.parse(data), { some: 'info', another: 'detail' })
30
+ res.statusCode = 200
31
+ res.setHeader('content-type', 'application/x-www-form-urlencoded')
32
+ res.end(str)
33
+ })
34
+ })
35
+
36
+ instance.post('/', (request, reply) => {
37
+ reply.from(`http://localhost:${target.address().port}`)
38
+ })
39
+
40
+ t.teardown(target.close.bind(target))
41
+
42
+ instance.listen(0, (err) => {
43
+ t.error(err)
44
+
45
+ target.listen(0, (err) => {
46
+ t.error(err)
47
+
48
+ get({
49
+ url: `http://localhost:${instance.server.address().port}`,
50
+ method: 'POST',
51
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
52
+ body: 'some=info&another=detail'
53
+ }, (err, res, data) => {
54
+ t.error(err)
55
+ t.equal(res.headers['content-type'], 'application/x-www-form-urlencoded')
56
+ t.same(JSON.parse(data), { some: 'info', another: 'detail' })
57
+ })
58
+ })
59
+ })
@@ -0,0 +1,56 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+
9
+ const instance = Fastify()
10
+ instance.register(From)
11
+
12
+ t.plan(9)
13
+ t.teardown(instance.close.bind(instance))
14
+
15
+ const target = http.createServer((req, res) => {
16
+ t.pass('request proxied')
17
+ t.equal(req.method, 'POST')
18
+ t.equal(req.headers['content-type'], 'text/plain')
19
+ let data = ''
20
+ req.setEncoding('utf8')
21
+ req.on('data', (d) => {
22
+ data += d
23
+ })
24
+ req.on('end', () => {
25
+ const str = data.toString()
26
+ t.same(str, 'this is plain text')
27
+ res.statusCode = 200
28
+ res.setHeader('content-type', 'text/plain')
29
+ res.end(str)
30
+ })
31
+ })
32
+
33
+ instance.post('/', (request, reply) => {
34
+ reply.from(`http://localhost:${target.address().port}`)
35
+ })
36
+
37
+ t.teardown(target.close.bind(target))
38
+
39
+ instance.listen(0, (err) => {
40
+ t.error(err)
41
+
42
+ target.listen(0, (err) => {
43
+ t.error(err)
44
+
45
+ get({
46
+ url: `http://localhost:${instance.server.address().port}`,
47
+ method: 'POST',
48
+ headers: { 'content-type': 'text/plain' },
49
+ body: 'this is plain text'
50
+ }, (err, res, data) => {
51
+ t.error(err)
52
+ t.equal(res.headers['content-type'], 'text/plain')
53
+ t.same(data.toString(), 'this is plain text')
54
+ })
55
+ })
56
+ })
@@ -0,0 +1,65 @@
1
+ 'use strict'
2
+
3
+ const t = require('tap')
4
+ const Fastify = require('fastify')
5
+ const From = require('..')
6
+ const http = require('http')
7
+ const get = require('simple-get').concat
8
+ const { parse } = require('querystring')
9
+
10
+ const instance = Fastify()
11
+ instance.register(From, {
12
+ contentTypesToEncode: ['application/x-www-form-urlencoded']
13
+ })
14
+
15
+ instance.addContentTypeParser(
16
+ 'application/x-www-form-urlencoded',
17
+ { parseAs: 'buffer', bodyLimit: 1000 },
18
+ (req, body, done) => done(null, parse(body.toString()))
19
+ )
20
+
21
+ t.plan(9)
22
+ t.teardown(instance.close.bind(instance))
23
+
24
+ const target = http.createServer((req, res) => {
25
+ t.pass('request proxied')
26
+ t.equal(req.method, 'POST')
27
+ t.equal(req.headers['content-type'], 'application/x-www-form-urlencoded')
28
+ let data = ''
29
+ req.setEncoding('utf8')
30
+ req.on('data', (d) => {
31
+ data += d
32
+ })
33
+ req.on('end', () => {
34
+ const str = data.toString()
35
+ t.same(JSON.parse(data), { some: 'info', another: 'detail' })
36
+ res.statusCode = 200
37
+ res.setHeader('content-type', 'application/x-www-form-urlencoded')
38
+ res.end(str)
39
+ })
40
+ })
41
+
42
+ instance.post('/', (request, reply) => {
43
+ reply.from(`http://localhost:${target.address().port}`)
44
+ })
45
+
46
+ t.teardown(target.close.bind(target))
47
+
48
+ instance.listen(0, (err) => {
49
+ t.error(err)
50
+
51
+ target.listen(0, (err) => {
52
+ t.error(err)
53
+
54
+ get({
55
+ url: `http://localhost:${instance.server.address().port}`,
56
+ method: 'POST',
57
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
58
+ body: 'some=info&another=detail'
59
+ }, (err, res, data) => {
60
+ t.error(err)
61
+ t.equal(res.headers['content-type'], 'application/x-www-form-urlencoded')
62
+ t.same(JSON.parse(data), { some: 'info', another: 'detail' })
63
+ })
64
+ })
65
+ })