@fastify/reply-from 10.0.0 → 11.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.
- package/.gitattributes +2 -0
- package/.github/workflows/ci.yml +1 -1
- package/.taprc +1 -9
- package/README.md +114 -29
- package/index.js +55 -47
- package/lib/request.js +32 -12
- package/lib/utils.js +8 -0
- package/package.json +25 -22
- package/test/async-route-handler.test.js +1 -1
- package/test/base-get.test.js +1 -1
- package/test/base-querystring.test.js +1 -1
- package/test/build-url.test.js +9 -2
- package/test/core-with-path-in-base.test.js +1 -1
- package/test/custom-undici-instance.test.js +1 -1
- package/test/disable-request-logging.test.js +1 -1
- package/test/fastify-multipart-incompatibility.test.js +3 -3
- package/test/fix-GHSA-v2v2-hph8-q5xp.test.js +47 -0
- package/test/full-delete-http2.test.js +52 -0
- package/test/full-get-test.test.js +1 -1
- package/test/full-https-get.test.js +3 -3
- package/test/full-post-extended-content-type.test.js +1 -1
- package/test/full-post-http2.test.js +2 -0
- package/test/full-post-stream-core.test.js +1 -1
- package/test/full-post-stream.test.js +1 -1
- package/test/full-post.test.js +1 -1
- package/test/full-querystring-rewrite-option-complex.test.js +1 -1
- package/test/full-querystring-rewrite-option-function-request.test.js +58 -0
- package/test/full-querystring-rewrite-option-function.test.js +2 -2
- package/test/full-querystring-rewrite-option.test.js +1 -1
- package/test/full-querystring-rewrite-string.test.js +1 -1
- package/test/full-querystring-rewrite.test.js +1 -1
- package/test/full-querystring.test.js +1 -1
- package/test/full-rewrite-body-content-type.test.js +1 -1
- package/test/full-rewrite-body-http.test.js +1 -1
- package/test/full-rewrite-body-to-empty-string.test.js +1 -1
- package/test/full-rewrite-body-to-null.test.js +1 -1
- package/test/full-rewrite-body.test.js +1 -1
- package/test/get-upstream-http.test.js +1 -1
- package/test/get-upstream-type.test.js +1 -1
- package/test/get-upstream-undici.test.js +1 -1
- package/test/get-with-body.test.js +1 -1
- package/test/head-with-body.test.js +7 -1
- package/test/http-agents.test.js +2 -2
- package/test/http-global-agent.test.js +1 -1
- package/test/http-http2.test.js +2 -0
- package/test/http-retry.test.js +1 -1
- package/test/http-timeout.test.js +0 -2
- package/test/http2-http2.test.js +4 -2
- package/test/http2-https.test.js +2 -2
- package/test/http2-invalid-base.test.js +1 -1
- package/test/http2-timeout-disabled.test.js +85 -0
- package/test/http2-timeout.test.js +2 -0
- package/test/http2-unix-socket.test.js +1 -1
- package/test/https-agents.test.js +4 -4
- package/test/https-global-agent.test.js +3 -3
- package/test/method.test.js +70 -0
- package/test/modifyCoreObjects-false.test.js +1 -1
- package/test/no-body-opts-with-get.test.js +1 -1
- package/test/no-body-opts-with-head.test.js +1 -1
- package/test/no-stream-body-option.test.js +2 -2
- package/test/on-error.test.js +11 -15
- package/test/onResponse.test.js +4 -3
- package/test/padded-body.test.js +1 -1
- package/test/post-formbody.test.js +1 -1
- package/test/post-plain-text.test.js +1 -1
- package/test/post-with-custom-encoded-contenttype.test.js +2 -2
- package/test/post-with-octet-stream.test.js +2 -2
- package/test/retry-on-503.test.js +1 -1
- package/test/retry-with-a-custom-handler.test.js +186 -0
- package/test/rewrite-headers-type.test.js +1 -1
- package/test/rewrite-headers.test.js +1 -1
- package/test/rewrite-request-headers-type.test.js +1 -1
- package/test/rewrite-request-headers.test.js +1 -1
- package/test/transform-body.test.js +3 -3
- package/test/undici-agent.test.js +2 -2
- package/test/undici-body.test.js +1 -1
- package/test/undici-connect-timeout.test.js +10 -14
- package/test/undici-custom-dispatcher.test.js +73 -0
- package/test/undici-global-agent.test.js +1 -1
- package/test/undici-no-destroy.test.js +29 -0
- package/test/undici-options.test.js +1 -1
- package/test/undici-proxy-agent.test.js +81 -0
- package/test/undici-retry.test.js +1 -1
- package/test/undici-timeout-body-partial.test.js +15 -19
- package/test/undici-timeout-body.test.js +13 -17
- package/test/undici-timeout.test.js +11 -15
- package/test/undici-with-path-in-base.test.js +1 -1
- package/test/undici.test.js +1 -1
- package/test/unix-http-undici-from.test.js +3 -3
- package/test/unix-http-undici.test.js +3 -3
- package/test/unix-http.test.js +3 -3
- package/test/unix-https-undici.test.js +4 -4
- package/test/unix-https.test.js +4 -4
- package/types/index.d.ts +37 -19
- package/types/index.test-d.ts +37 -10
package/lib/utils.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
1
3
|
function filterPseudoHeaders (headers) {
|
|
2
4
|
const dest = {}
|
|
3
5
|
const headersKeys = Object.keys(headers)
|
|
@@ -57,6 +59,12 @@ function stripHttp1ConnectionHeaders (headers) {
|
|
|
57
59
|
// issue ref: https://github.com/fastify/fast-proxy/issues/42
|
|
58
60
|
function buildURL (source, reqBase) {
|
|
59
61
|
let baseOrigin = reqBase ? new URL(reqBase).href : undefined
|
|
62
|
+
|
|
63
|
+
// To make sure we don't accidentally override the base path
|
|
64
|
+
if (baseOrigin && source.length > 1 && source[0] === '/' && source[1] === '/') {
|
|
65
|
+
source = '.' + source
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
const dest = new URL(source, reqBase)
|
|
61
69
|
|
|
62
70
|
// if base is specified, source url should not override it
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastify/reply-from",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0",
|
|
4
4
|
"description": "forward your HTTP request to another server, for fastify",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"type": "commonjs",
|
|
6
7
|
"types": "types/index.d.ts",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"lint": "standard | snazzy",
|
|
9
|
-
"lint:fix": "standard --fix",
|
|
10
|
+
"lint:fix": "standard --fix | snazzy",
|
|
10
11
|
"test": "npm run test:unit && npm run test:typescript",
|
|
11
12
|
"test:unit": "tap",
|
|
12
13
|
"test:typescript": "tsd"
|
|
@@ -28,34 +29,36 @@
|
|
|
28
29
|
},
|
|
29
30
|
"homepage": "https://github.com/fastify/fastify-reply-from#readme",
|
|
30
31
|
"devDependencies": {
|
|
31
|
-
"@fastify/formbody": "^
|
|
32
|
-
"@fastify/multipart": "^
|
|
33
|
-
"@fastify/pre-commit": "^2.0
|
|
34
|
-
"@sinonjs/fake-timers": "^
|
|
35
|
-
"@types/node": "^
|
|
36
|
-
"@types/tap": "^15.0.
|
|
37
|
-
"fastify": "^
|
|
32
|
+
"@fastify/formbody": "^8.0.0",
|
|
33
|
+
"@fastify/multipart": "^9.0.0",
|
|
34
|
+
"@fastify/pre-commit": "^2.1.0",
|
|
35
|
+
"@sinonjs/fake-timers": "^13.0.1",
|
|
36
|
+
"@types/node": "^22.0.0",
|
|
37
|
+
"@types/tap": "^15.0.11",
|
|
38
|
+
"fastify": "^5.0.0-alpha.4",
|
|
38
39
|
"form-data": "^4.0.0",
|
|
39
|
-
"got": "^11.8.
|
|
40
|
+
"got": "^11.8.6",
|
|
40
41
|
"h2url": "^0.2.0",
|
|
41
|
-
"msgpack5": "^6.0.
|
|
42
|
-
"nock": "^13.
|
|
42
|
+
"msgpack5": "^6.0.2",
|
|
43
|
+
"nock": "^13.5.4",
|
|
44
|
+
"proxy": "^2.1.1",
|
|
43
45
|
"proxyquire": "^2.1.3",
|
|
46
|
+
"semver": "^7.6.0",
|
|
44
47
|
"simple-get": "^4.0.1",
|
|
45
48
|
"snazzy": "^9.0.0",
|
|
46
|
-
"split2": "^4.
|
|
47
|
-
"standard": "^17.
|
|
48
|
-
"tap": "^
|
|
49
|
-
"tsd": "^0.
|
|
49
|
+
"split2": "^4.2.0",
|
|
50
|
+
"standard": "^17.1.0",
|
|
51
|
+
"tap": "^18.7.2",
|
|
52
|
+
"tsd": "^0.31.0"
|
|
50
53
|
},
|
|
51
54
|
"dependencies": {
|
|
52
|
-
"@fastify/error": "^
|
|
55
|
+
"@fastify/error": "^4.0.0",
|
|
53
56
|
"end-of-stream": "^1.4.4",
|
|
54
|
-
"fast-
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"undici": "^
|
|
57
|
+
"fast-content-type-parse": "^2.0.0",
|
|
58
|
+
"fast-querystring": "^1.1.2",
|
|
59
|
+
"fastify-plugin": "^4.5.1",
|
|
60
|
+
"toad-cache": "^3.7.0",
|
|
61
|
+
"undici": "^6.11.1"
|
|
59
62
|
},
|
|
60
63
|
"pre-commit": [
|
|
61
64
|
"lint",
|
package/test/base-get.test.js
CHANGED
package/test/build-url.test.js
CHANGED
|
@@ -42,12 +42,19 @@ test('should handle default port in base', (t) => {
|
|
|
42
42
|
t.equal(url.href, 'https://localhost/hi')
|
|
43
43
|
})
|
|
44
44
|
|
|
45
|
+
test('should append instead of override base', (t) => {
|
|
46
|
+
t.plan(2)
|
|
47
|
+
let url = buildURL('//10.0.0.10/hi', 'http://localhost')
|
|
48
|
+
t.equal(url.href, 'http://localhost//10.0.0.10/hi')
|
|
49
|
+
|
|
50
|
+
url = buildURL('//httpbin.org/hi', 'http://localhost')
|
|
51
|
+
t.equal(url.href, 'http://localhost//httpbin.org/hi')
|
|
52
|
+
})
|
|
53
|
+
|
|
45
54
|
const errorInputs = [
|
|
46
|
-
{ source: '//10.0.0.10/hi', base: 'http://localhost' },
|
|
47
55
|
{ source: 'http://10.0.0.10/hi', base: 'http://localhost' },
|
|
48
56
|
{ source: 'https://10.0.0.10/hi', base: 'http://localhost' },
|
|
49
57
|
{ source: 'blah://10.0.0.10/hi', base: 'http://localhost' },
|
|
50
|
-
{ source: '//httpbin.org/hi', base: 'http://localhost' },
|
|
51
58
|
{ source: 'urn:foo:bar', base: 'http://localhost' },
|
|
52
59
|
{ source: 'http://localhost/private', base: 'http://localhost/exposed/' },
|
|
53
60
|
{ source: 'http://localhost/exposed-extra', base: 'http://localhost/exposed' },
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const path = require('path')
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
5
|
const t = require('tap')
|
|
6
6
|
const Fastify = require('fastify')
|
|
7
7
|
const From = require('..')
|
|
8
8
|
const Multipart = require('@fastify/multipart')
|
|
9
|
-
const http = require('http')
|
|
9
|
+
const http = require('node:http')
|
|
10
10
|
const get = require('simple-get').concat
|
|
11
11
|
const FormData = require('form-data')
|
|
12
12
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const fastify = require('fastify')
|
|
5
|
+
const get = require('simple-get').concat
|
|
6
|
+
const From = require('..')
|
|
7
|
+
|
|
8
|
+
const upstream = fastify()
|
|
9
|
+
t.teardown(upstream.close.bind(upstream))
|
|
10
|
+
t.plan(4)
|
|
11
|
+
|
|
12
|
+
upstream.post('/test', async (request, reply) => {
|
|
13
|
+
if (typeof request.body === 'object') {
|
|
14
|
+
return 'not ok'
|
|
15
|
+
}
|
|
16
|
+
return 'ok'
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
upstream.listen({ port: 0 }, function (err) {
|
|
20
|
+
t.error(err)
|
|
21
|
+
|
|
22
|
+
const app = fastify()
|
|
23
|
+
app.register(From)
|
|
24
|
+
t.teardown(app.close.bind(app))
|
|
25
|
+
|
|
26
|
+
app.post('/test', (request, reply) => {
|
|
27
|
+
if (request.body.method === 'invalid_method') {
|
|
28
|
+
return reply.code(400).send({ message: 'payload contains invalid method' })
|
|
29
|
+
}
|
|
30
|
+
reply.from(`http://127.0.0.1:${upstream.server.address().port}/test`)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
app.listen({ port: 0 }, function (err) {
|
|
34
|
+
t.error(err)
|
|
35
|
+
|
|
36
|
+
get({
|
|
37
|
+
url: `http://127.0.0.1:${app.server.address().port}/test`,
|
|
38
|
+
headers: { 'content-type': 'application/json ; charset=utf-8' },
|
|
39
|
+
// eslint-disable-next-line no-useless-escape
|
|
40
|
+
body: '"{\\\"method\\\":\\\"invalid_method\\\"}"',
|
|
41
|
+
method: 'POST'
|
|
42
|
+
}, (err, res, data) => {
|
|
43
|
+
t.error(err)
|
|
44
|
+
t.equal(data.toString(), 'ok')
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { test } = require('tap')
|
|
4
|
+
const Fastify = require('fastify')
|
|
5
|
+
const From = require('..')
|
|
6
|
+
const got = require('got')
|
|
7
|
+
|
|
8
|
+
test('http -> http2', async function (t) {
|
|
9
|
+
const instance = Fastify()
|
|
10
|
+
|
|
11
|
+
t.teardown(instance.close.bind(instance))
|
|
12
|
+
|
|
13
|
+
const target = Fastify({
|
|
14
|
+
http2: true
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
target.delete('/', (request, reply) => {
|
|
18
|
+
t.pass('request proxied')
|
|
19
|
+
reply.code(200).header('x-my-header', 'hello!').send({
|
|
20
|
+
hello: 'world'
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
instance.delete('/', (request, reply) => {
|
|
25
|
+
reply.from()
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
t.teardown(target.close.bind(target))
|
|
29
|
+
|
|
30
|
+
await target.listen({ port: 0 })
|
|
31
|
+
|
|
32
|
+
instance.register(From, {
|
|
33
|
+
base: `http://localhost:${target.server.address().port}`,
|
|
34
|
+
http2: true
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
await instance.listen({ port: 0 })
|
|
38
|
+
|
|
39
|
+
const { headers, body, statusCode } = await got(
|
|
40
|
+
`http://localhost:${instance.server.address().port}`,
|
|
41
|
+
{
|
|
42
|
+
method: 'DELETE',
|
|
43
|
+
responseType: 'json'
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
t.equal(statusCode, 200)
|
|
47
|
+
t.equal(headers['x-my-header'], 'hello!')
|
|
48
|
+
t.match(headers['content-type'], /application\/json/)
|
|
49
|
+
t.same(body, { hello: 'world' })
|
|
50
|
+
instance.close()
|
|
51
|
+
target.close()
|
|
52
|
+
})
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
const t = require('tap')
|
|
4
4
|
const Fastify = require('fastify')
|
|
5
5
|
const From = require('..')
|
|
6
|
-
const https = require('https')
|
|
6
|
+
const https = require('node:https')
|
|
7
7
|
const get = require('simple-get').concat
|
|
8
|
-
const fs = require('fs')
|
|
9
|
-
const path = require('path')
|
|
8
|
+
const fs = require('node:fs')
|
|
9
|
+
const path = require('node:path')
|
|
10
10
|
const certs = {
|
|
11
11
|
key: fs.readFileSync(path.join(__dirname, 'fixtures', 'fastify.key')),
|
|
12
12
|
cert: fs.readFileSync(path.join(__dirname, 'fixtures', 'fastify.cert'))
|
package/test/full-post.test.js
CHANGED
|
@@ -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('node:http')
|
|
7
|
+
const get = require('simple-get').concat
|
|
8
|
+
const querystring = require('node:querystring')
|
|
9
|
+
|
|
10
|
+
const instance = Fastify()
|
|
11
|
+
|
|
12
|
+
instance.addHook('preHandler', (request, reply, done) => {
|
|
13
|
+
request.addedVal = 'test'
|
|
14
|
+
done()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
t.plan(10)
|
|
18
|
+
t.teardown(instance.close.bind(instance))
|
|
19
|
+
|
|
20
|
+
const target = http.createServer((req, res) => {
|
|
21
|
+
t.pass('request proxied')
|
|
22
|
+
t.equal(req.method, 'GET')
|
|
23
|
+
t.equal(req.url, '/world?q=test')
|
|
24
|
+
res.statusCode = 205
|
|
25
|
+
res.setHeader('Content-Type', 'text/plain')
|
|
26
|
+
res.setHeader('x-my-header', 'hello!')
|
|
27
|
+
res.end('hello world')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
instance.get('/hello', (request, reply) => {
|
|
31
|
+
reply.from(`http://localhost:${target.address().port}/world?a=b`, {
|
|
32
|
+
queryString (search, reqUrl, request) {
|
|
33
|
+
return querystring.stringify({ q: request.addedVal })
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
t.teardown(target.close.bind(target))
|
|
39
|
+
|
|
40
|
+
target.listen({ port: 0 }, (err) => {
|
|
41
|
+
t.error(err)
|
|
42
|
+
|
|
43
|
+
instance.register(From)
|
|
44
|
+
|
|
45
|
+
instance.listen({ port: 0 }, (err) => {
|
|
46
|
+
t.error(err)
|
|
47
|
+
|
|
48
|
+
get(`http://localhost:${instance.server.address().port}/hello?a=b`, (err, res, data) => {
|
|
49
|
+
t.error(err)
|
|
50
|
+
t.equal(res.headers['content-type'], 'text/plain')
|
|
51
|
+
t.equal(res.headers['x-my-header'], 'hello!')
|
|
52
|
+
t.equal(res.statusCode, 205)
|
|
53
|
+
t.equal(data.toString(), 'hello world')
|
|
54
|
+
instance.close()
|
|
55
|
+
target.close()
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
})
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
const t = require('tap')
|
|
4
4
|
const Fastify = require('fastify')
|
|
5
5
|
const From = require('..')
|
|
6
|
-
const http = require('http')
|
|
6
|
+
const http = require('node:http')
|
|
7
7
|
const get = require('simple-get').concat
|
|
8
|
-
const querystring = require('querystring')
|
|
8
|
+
const querystring = require('node:querystring')
|
|
9
9
|
|
|
10
10
|
const instance = Fastify()
|
|
11
11
|
|
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
const t = require('tap')
|
|
4
4
|
const Fastify = require('fastify')
|
|
5
5
|
const From = require('..')
|
|
6
|
-
const http = require('http')
|
|
6
|
+
const http = require('node:http')
|
|
7
7
|
const get = require('simple-get').concat
|
|
8
|
+
const semver = require('semver')
|
|
9
|
+
|
|
10
|
+
if (semver.gte(process.version, '20.2.0')) {
|
|
11
|
+
t.comment('skip this test on node >= 20.2.0 as it is current broken')
|
|
12
|
+
process.exit(0)
|
|
13
|
+
}
|
|
8
14
|
|
|
9
15
|
const instance = Fastify()
|
|
10
16
|
|
package/test/http-agents.test.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
const t = require('tap')
|
|
4
4
|
const Fastify = require('fastify')
|
|
5
5
|
const From = require('..')
|
|
6
|
-
const http = require('http')
|
|
7
|
-
const https = require('https')
|
|
6
|
+
const http = require('node:http')
|
|
7
|
+
const https = require('node:https')
|
|
8
8
|
const get = require('simple-get').concat
|
|
9
9
|
|
|
10
10
|
const instance = Fastify()
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const { test } = require('tap')
|
|
4
4
|
const Fastify = require('fastify')
|
|
5
5
|
const From = require('..')
|
|
6
|
-
const http = require('http')
|
|
6
|
+
const http = require('node:http')
|
|
7
7
|
const get = require('simple-get').concat
|
|
8
8
|
|
|
9
9
|
test('http global agent is used, but not destroyed', async (t) => {
|
package/test/http-http2.test.js
CHANGED
|
@@ -43,6 +43,8 @@ test('http -> http2', async (t) => {
|
|
|
43
43
|
t.equal(err.response.headers['x-my-header'], 'hello!')
|
|
44
44
|
t.match(err.response.headers['content-type'], /application\/json/)
|
|
45
45
|
t.same(JSON.parse(err.response.body), { hello: 'world' })
|
|
46
|
+
instance.close()
|
|
47
|
+
target.close()
|
|
46
48
|
return
|
|
47
49
|
}
|
|
48
50
|
|
package/test/http-retry.test.js
CHANGED