@fastify/reply-from 12.0.0 → 12.0.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/.github/dependabot.yml +1 -1
- package/.github/workflows/ci.yml +0 -1
- package/README.md +16 -16
- package/eslint.config.js +6 -0
- package/examples/example.js +2 -2
- package/index.js +6 -8
- package/lib/request.js +4 -4
- package/package.json +37 -10
- package/test/async-route-handler.test.js +1 -1
- package/test/base-get.test.js +1 -1
- package/test/base-path.test.js +2 -2
- package/test/base-querystring.test.js +1 -1
- package/test/core-with-path-in-base.test.js +1 -1
- package/test/custom-undici-instance.test.js +2 -2
- package/test/disable-request-logging.test.js +3 -3
- package/test/fastify-multipart-incompatibility.test.js +2 -2
- package/test/fix-GHSA-v2v2-hph8-q5xp.test.js +52 -36
- package/test/full-delete-http2.test.js +2 -2
- package/test/full-get-test.test.js +1 -1
- package/test/full-https-get.test.js +1 -1
- package/test/full-post-extended-content-type.test.js +1 -1
- package/test/full-post-http2.test.js +1 -1
- package/test/full-post-stream-core.test.js +3 -3
- package/test/full-post-stream.test.js +3 -3
- package/test/full-post.test.js +2 -2
- package/test/full-querystring-rewrite-option-complex.test.js +1 -1
- package/test/full-querystring-rewrite-option-function-request.test.js +3 -3
- package/test/full-querystring-rewrite-option-function.test.js +1 -1
- 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 +10 -7
- package/test/full-rewrite-body-http.test.js +2 -2
- package/test/full-rewrite-body-to-empty-string.test.js +2 -2
- package/test/full-rewrite-body-to-null.test.js +2 -2
- package/test/full-rewrite-body.test.js +2 -2
- package/test/get-upstream-http.test.js +3 -3
- 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 +1 -7
- package/test/host-header.test.js +4 -4
- package/test/http-agents.test.js +1 -1
- package/test/http-global-agent.test.js +1 -1
- package/test/http-http2.test.js +2 -2
- package/test/http-invalid-target.test.js +1 -1
- package/test/http-retry.test.js +3 -3
- package/test/http-timeout.test.js +4 -4
- package/test/http2-http2.test.js +2 -2
- package/test/http2-https.test.js +2 -2
- package/test/http2-invalid-target.test.js +1 -1
- package/test/http2-target-crash.test.js +2 -2
- package/test/http2-target-multi-crash.test.js +1 -1
- package/test/http2-timeout-disabled.test.js +2 -2
- package/test/http2-timeout.test.js +4 -4
- package/test/https-agents.test.js +1 -1
- package/test/https-global-agent.test.js +1 -1
- package/test/method.test.js +3 -3
- package/test/modifyCoreObjects-false.test.js +1 -1
- package/test/no-body-opts-with-get.test.js +2 -2
- package/test/no-body-opts-with-head.test.js +2 -2
- package/test/no-stream-body-option.test.js +2 -2
- package/test/on-error.test.js +2 -2
- package/test/on-invalid-upstream-response.test.js +1 -1
- package/test/padded-body.test.js +2 -2
- 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 +5 -5
- package/test/retry-on-503.test.js +4 -4
- package/test/retry-with-a-custom-handler.test.js +7 -7
- package/test/rewrite-headers-type.test.js +2 -2
- package/test/rewrite-headers.test.js +3 -3
- package/test/rewrite-request-headers-type.test.js +2 -2
- package/test/rewrite-request-headers.test.js +2 -2
- package/test/transform-body.test.js +3 -3
- package/test/undici-agent.test.js +2 -2
- package/test/undici-body.test.js +3 -3
- package/test/undici-chaining.test.js +3 -3
- package/test/undici-connect-timeout.test.js +2 -2
- package/test/undici-custom-dispatcher.test.js +2 -2
- package/test/undici-global-agent.test.js +2 -2
- package/test/undici-no-destroy.test.js +1 -1
- package/test/undici-options.test.js +2 -2
- package/test/undici-proxy-agent.test.js +47 -28
- package/test/undici-retry.test.js +3 -3
- package/test/undici-timeout-body-partial.test.js +1 -1
- package/test/undici-timeout-body.test.js +1 -1
- package/test/undici-timeout.test.js +2 -2
- package/test/undici-with-path-in-base.test.js +1 -1
- package/test/undici.test.js +1 -1
- package/test/unexpected-error.test.js +2 -2
- package/test/unix-http-undici-from.test.js +3 -3
- package/test/unix-http-undici.test.js +1 -1
- package/test/unix-http.test.js +1 -1
- package/test/unix-https-undici.test.js +1 -1
- package/test/unix-https.test.js +1 -1
- package/types/index.d.ts +10 -11
- package/types/index.test-d.ts +138 -108
package/.github/dependabot.yml
CHANGED
package/.github/workflows/ci.yml
CHANGED
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @fastify/reply-from
|
|
2
2
|
|
|
3
|
-
[](https://github.com/fastify/fastify-reply-from/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@fastify/reply-from)
|
|
5
|
-
[](https://github.com/neostandard/neostandard)
|
|
6
6
|
|
|
7
7
|
Fastify plugin to forward the current HTTP request to another server.
|
|
8
8
|
HTTP2 to HTTP is supported too.
|
|
@@ -14,7 +14,7 @@ npm i @fastify/reply-from
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Compatibility with @fastify/multipart
|
|
17
|
-
`@fastify/reply-from` and [`@fastify/multipart`](https://github.com/fastify/fastify-multipart) should not be registered as sibling plugins nor should they be registered in plugins
|
|
17
|
+
`@fastify/reply-from` and [`@fastify/multipart`](https://github.com/fastify/fastify-multipart) should not be registered as sibling plugins nor should they be registered in plugins that have a parent-child relationship.`<br>` The two plugins are incompatible, in the sense that the behavior of `@fastify/reply-from` might not be the expected one when the above-mentioned conditions are not respected.`<br>` This is due to the fact that `@fastify/multipart` consumes the multipart content by parsing it, hence this content is not forwarded to the target service by `@fastify/reply-from`.`<br>`
|
|
18
18
|
However, the two plugins may be used within the same fastify instance, at the condition that they belong to disjoint branches of the fastify plugins hierarchy tree.
|
|
19
19
|
|
|
20
20
|
## Usage
|
|
@@ -83,10 +83,10 @@ proxy.register(require('@fastify/reply-from'), {
|
|
|
83
83
|
#### `undici`
|
|
84
84
|
|
|
85
85
|
By default, [undici](https://github.com/nodejs/undici) will be used to perform the HTTP/1.1
|
|
86
|
-
requests. Enabling this
|
|
86
|
+
requests. Enabling this option should guarantee
|
|
87
87
|
20-50% more throughput.
|
|
88
88
|
|
|
89
|
-
This
|
|
89
|
+
This option controls the settings of the undici client, like so:
|
|
90
90
|
|
|
91
91
|
```js
|
|
92
92
|
proxy.register(require('@fastify/reply-from'), {
|
|
@@ -167,7 +167,7 @@ proxy.register(require('@fastify/reply-from'), {
|
|
|
167
167
|
|
|
168
168
|
#### `http2`
|
|
169
169
|
|
|
170
|
-
You can either set `http2` to `true` or set the settings object to connect to
|
|
170
|
+
You can either set `http2` to `true` or set the settings object to connect to an HTTP/2 server.
|
|
171
171
|
The `http2` settings object has the shape of:
|
|
172
172
|
|
|
173
173
|
```js
|
|
@@ -188,7 +188,7 @@ proxy.register(require('@fastify/reply-from'), {
|
|
|
188
188
|
|
|
189
189
|
#### `disableRequestLogging`
|
|
190
190
|
|
|
191
|
-
By default package will issue log messages when a request is received. By setting this option to true, these log messages will be disabled.
|
|
191
|
+
By default, the package will issue log messages when a request is received. By setting this option to true, these log messages will be disabled.
|
|
192
192
|
|
|
193
193
|
Default for `disableRequestLogging` will be `false`. To disable the log messages set `disableRequestLogging` to `true`.
|
|
194
194
|
|
|
@@ -206,7 +206,7 @@ The number of parsed URLs that will be cached. Default: `100`.
|
|
|
206
206
|
#### `disableCache`
|
|
207
207
|
|
|
208
208
|
This option will disable the URL caching.
|
|
209
|
-
This cache is dedicated to
|
|
209
|
+
This cache is dedicated to reducing the amount of URL object generation.
|
|
210
210
|
Generating URLs is a main bottleneck of this module, please disable this cache with caution.
|
|
211
211
|
|
|
212
212
|
#### `contentTypesToEncode`
|
|
@@ -231,7 +231,7 @@ This plugin will always retry on 503 errors, _unless_ `retryMethods` does not co
|
|
|
231
231
|
|
|
232
232
|
#### `globalAgent`
|
|
233
233
|
|
|
234
|
-
Enables the possibility to
|
|
234
|
+
Enables the possibility to explicitly opt-in for global agents.
|
|
235
235
|
|
|
236
236
|
Usage for undici global agent:
|
|
237
237
|
|
|
@@ -274,7 +274,7 @@ By Default: `false`
|
|
|
274
274
|
|
|
275
275
|
This plugin will always retry on `GET` requests that returns 503 errors, _unless_ `retryMethods` does not contain `GET`.
|
|
276
276
|
|
|
277
|
-
This option
|
|
277
|
+
This option sets the limit on how many times the plugin should retry the request, specifically for 503 errors.
|
|
278
278
|
|
|
279
279
|
By Default: 10
|
|
280
280
|
|
|
@@ -293,7 +293,7 @@ If a `handler` is passed to the `retryDelay` object the onus is on the client to
|
|
|
293
293
|
- `res` is the raw response returned by the underlying agent (if available) __Note__: this object is not a Fastify response, but instead the low-level response from the agent. This property may be null if no response was obtained at all, like from a connection reset or timeout.
|
|
294
294
|
- `attempt` in the object callback refers to the current retriesAttempt number. You are given the freedom to use this in concert with the retryCount property set to handle retries
|
|
295
295
|
- `getDefaultRetry` refers to the default retry handler. If this callback returns not null and you wish to handle those case of errors simply invoke it as done below.
|
|
296
|
-
- `retriesCount` refers to the retriesCount property a client passes to reply-from. Note if the client does not explicitly set this value it will default to 0. The objective value here is to avoid hard-coding and seeing the retriesCount set. It is your
|
|
296
|
+
- `retriesCount` refers to the retriesCount property a client passes to reply-from. Note if the client does not explicitly set this value it will default to 0. The objective value here is to avoid hard-coding and seeing the retriesCount set. It is your prerogative to ensure that you ensure the value here is as you wish (and not `0` if not intended to be as a result of a lack of not setting it).
|
|
297
297
|
|
|
298
298
|
Given example
|
|
299
299
|
|
|
@@ -339,14 +339,14 @@ const customRetryLogic = ({req, res, err, getDefaultRetry}: RetryDetails) => {
|
|
|
339
339
|
The plugin decorates the
|
|
340
340
|
[`Reply`](https://fastify.dev/docs/latest/Reference/Reply)
|
|
341
341
|
instance with a `from` method, which will reply to the original request
|
|
342
|
-
__from the desired source__. The options allows
|
|
342
|
+
__from the desired source__. The options allows overrides of any part of
|
|
343
343
|
the request or response being sent or received to/from the source.
|
|
344
344
|
|
|
345
345
|
**Note: If `base` is specified in plugin options, the `source` here should not override the host/origin.**
|
|
346
346
|
|
|
347
347
|
#### `onResponse(request, reply, response)`
|
|
348
348
|
|
|
349
|
-
Called when
|
|
349
|
+
Called when an HTTP response is received from the source. Passed the original source `request`, the in-progress reply to the source as `reply`, and the ongoing `response` from the upstream server.
|
|
350
350
|
|
|
351
351
|
The default behavior is `reply.send(response.stream)`, which will be disabled if the
|
|
352
352
|
option is specified.
|
|
@@ -367,10 +367,10 @@ the `content-length` header.
|
|
|
367
367
|
|
|
368
368
|
#### `onError(reply, error)`
|
|
369
369
|
|
|
370
|
-
Called when
|
|
370
|
+
Called when an HTTP response is received with error from the source.
|
|
371
371
|
The default behavior is `reply.send(error)`, which will be disabled if the
|
|
372
372
|
option is specified.
|
|
373
|
-
It must reply the error.
|
|
373
|
+
It must reply with the error.
|
|
374
374
|
|
|
375
375
|
#### `rewriteHeaders(headers, request)`
|
|
376
376
|
|
|
@@ -387,7 +387,7 @@ It must return the new headers object.
|
|
|
387
387
|
|
|
388
388
|
#### `getUpstream(request, base)`
|
|
389
389
|
|
|
390
|
-
Called to get upstream destination, before the request is
|
|
390
|
+
Called to get upstream destination, before the request is sent. Useful when you want to decide which target server to call based on the request data.
|
|
391
391
|
Helpful for a gradual rollout of new services.
|
|
392
392
|
Parameters are the Fastify request and the base string from the plugin options.
|
|
393
393
|
It must return the upstream destination.
|
package/eslint.config.js
ADDED
package/examples/example.js
CHANGED
|
@@ -6,7 +6,7 @@ const target = Fastify({
|
|
|
6
6
|
logger: true
|
|
7
7
|
})
|
|
8
8
|
|
|
9
|
-
target.get('/', (
|
|
9
|
+
target.get('/', (_request, reply) => {
|
|
10
10
|
reply.send('hello world')
|
|
11
11
|
})
|
|
12
12
|
|
|
@@ -19,7 +19,7 @@ proxy.register(require('..'), {
|
|
|
19
19
|
base: 'http://localhost:3001/'
|
|
20
20
|
})
|
|
21
21
|
|
|
22
|
-
proxy.get('/', (
|
|
22
|
+
proxy.get('/', (_request, reply) => {
|
|
23
23
|
reply.from('/')
|
|
24
24
|
})
|
|
25
25
|
|
package/index.js
CHANGED
|
@@ -149,7 +149,7 @@ const fastifyReplyFrom = fp(function from (fastify, opts, next) {
|
|
|
149
149
|
// Magic number, so why not 42? We might want to make this configurable.
|
|
150
150
|
let retryAfter = 42 * Math.random() * (retries + 1)
|
|
151
151
|
|
|
152
|
-
if (res
|
|
152
|
+
if (res?.headers['retry-after']) {
|
|
153
153
|
retryAfter = res.headers['retry-after']
|
|
154
154
|
}
|
|
155
155
|
if (res && res.statusCode === 503 && req.method === 'GET') {
|
|
@@ -164,9 +164,7 @@ const fastifyReplyFrom = fp(function from (fastify, opts, next) {
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
if (retryDelay) {
|
|
167
|
-
requestImpl = createRequestRetry(request, this, (req, res, err, retries) => {
|
|
168
|
-
return retryDelay({ err, req, res, attempt: retries, getDefaultDelay, retriesCount })
|
|
169
|
-
})
|
|
167
|
+
requestImpl = createRequestRetry(request, this, (req, res, err, retries) => retryDelay({ err, req, res, attempt: retries, getDefaultDelay, retriesCount }))
|
|
170
168
|
} else {
|
|
171
169
|
requestImpl = createRequestRetry(request, this, getDefaultDelay)
|
|
172
170
|
}
|
|
@@ -223,7 +221,7 @@ const fastifyReplyFrom = fp(function from (fastify, opts, next) {
|
|
|
223
221
|
done()
|
|
224
222
|
})
|
|
225
223
|
|
|
226
|
-
fastify.onClose((
|
|
224
|
+
fastify.onClose((_fastify, next) => {
|
|
227
225
|
close()
|
|
228
226
|
// let the event loop do a full run so that it can
|
|
229
227
|
// actually destroy those sockets
|
|
@@ -257,15 +255,15 @@ function getQueryString (search, reqUrl, opts, request) {
|
|
|
257
255
|
return ''
|
|
258
256
|
}
|
|
259
257
|
|
|
260
|
-
function headersNoOp (headers,
|
|
258
|
+
function headersNoOp (headers, _originalReq) {
|
|
261
259
|
return headers
|
|
262
260
|
}
|
|
263
261
|
|
|
264
|
-
function requestHeadersNoOp (
|
|
262
|
+
function requestHeadersNoOp (_originalReq, headers) {
|
|
265
263
|
return headers
|
|
266
264
|
}
|
|
267
265
|
|
|
268
|
-
function upstreamNoOp (
|
|
266
|
+
function upstreamNoOp (_req, base) {
|
|
269
267
|
return base
|
|
270
268
|
}
|
|
271
269
|
|
package/lib/request.js
CHANGED
|
@@ -75,7 +75,7 @@ function buildRequest (opts) {
|
|
|
75
75
|
if (isHttp2) {
|
|
76
76
|
return { request: handleHttp2Req, close, retryOnError: 'ECONNRESET' }
|
|
77
77
|
} else if (hasUndiciOptions) {
|
|
78
|
-
if (opts.base
|
|
78
|
+
if (opts.base?.startsWith('unix+')) {
|
|
79
79
|
const undiciOpts = getUndiciOptions(opts.undici)
|
|
80
80
|
undiciOpts.socketPath = decodeURIComponent(new URL(opts.base).host)
|
|
81
81
|
const protocol = opts.base.startsWith('unix+https') ? 'https' : 'http'
|
|
@@ -102,8 +102,8 @@ function buildRequest (opts) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
if (hasUndiciOptions) {
|
|
105
|
-
undiciAgent
|
|
106
|
-
undiciInstance
|
|
105
|
+
undiciAgent?.destroy()
|
|
106
|
+
undiciInstance?.destroy()
|
|
107
107
|
} else if (!isHttp2) {
|
|
108
108
|
agents['http:'].destroy()
|
|
109
109
|
agents['https:'].destroy()
|
|
@@ -304,7 +304,7 @@ function getAgentOptions (opts) {
|
|
|
304
304
|
keepAliveMsecs: 60 * 1000, // 1 minute
|
|
305
305
|
maxSockets: 2048,
|
|
306
306
|
maxFreeSockets: 2048,
|
|
307
|
-
...(opts.http
|
|
307
|
+
...(opts.http?.agentOptions)
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastify/reply-from",
|
|
3
|
-
"version": "12.0.
|
|
3
|
+
"version": "12.0.2",
|
|
4
4
|
"description": "forward your HTTP request to another server, for fastify",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"types": "types/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"lint": "
|
|
10
|
-
"lint:fix": "
|
|
9
|
+
"lint": "eslint",
|
|
10
|
+
"lint:fix": "eslint --fix",
|
|
11
11
|
"test": "npm run test:unit && npm run test:typescript",
|
|
12
12
|
"test:unit": "tap",
|
|
13
13
|
"test:typescript": "tsd"
|
|
@@ -23,31 +23,58 @@
|
|
|
23
23
|
"proxy"
|
|
24
24
|
],
|
|
25
25
|
"author": "Matteo Collina <hello@matteocollina.com>",
|
|
26
|
+
"contributors": [
|
|
27
|
+
{
|
|
28
|
+
"name": "James Sumners",
|
|
29
|
+
"url": "https://james.sumners.info"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "Manuel Spigolon",
|
|
33
|
+
"email": "behemoth89@gmail.com"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "Aras Abbasi",
|
|
37
|
+
"email": "aras.abbasi@gmail.com"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "Frazer Smith",
|
|
41
|
+
"email": "frazer.dev@icloud.com",
|
|
42
|
+
"url": "https://github.com/fdawgs"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
26
45
|
"license": "MIT",
|
|
27
46
|
"bugs": {
|
|
28
47
|
"url": "https://github.com/fastify/fastify-reply-from/issues"
|
|
29
48
|
},
|
|
30
49
|
"homepage": "https://github.com/fastify/fastify-reply-from#readme",
|
|
50
|
+
"funding": [
|
|
51
|
+
{
|
|
52
|
+
"type": "github",
|
|
53
|
+
"url": "https://github.com/sponsors/fastify"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "opencollective",
|
|
57
|
+
"url": "https://opencollective.com/fastify"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
31
60
|
"devDependencies": {
|
|
32
61
|
"@fastify/formbody": "^8.0.0",
|
|
33
62
|
"@fastify/multipart": "^9.0.0",
|
|
34
63
|
"@fastify/pre-commit": "^2.1.0",
|
|
35
|
-
"@sinonjs/fake-timers": "^
|
|
64
|
+
"@sinonjs/fake-timers": "^14.0.0",
|
|
36
65
|
"@types/node": "^22.0.0",
|
|
37
|
-
"@types/tap": "^
|
|
66
|
+
"@types/tap": "^18.0.0",
|
|
67
|
+
"eslint": "^9.17.0",
|
|
38
68
|
"fastify": "^5.0.0",
|
|
39
69
|
"form-data": "^4.0.0",
|
|
40
70
|
"got": "^11.8.6",
|
|
41
71
|
"h2url": "^0.2.0",
|
|
42
|
-
"
|
|
43
|
-
"nock": "^
|
|
72
|
+
"neostandard": "^0.12.0",
|
|
73
|
+
"nock": "^14.0.0",
|
|
44
74
|
"proxy": "^2.1.1",
|
|
45
75
|
"proxyquire": "^2.1.3",
|
|
46
|
-
"semver": "^7.6.0",
|
|
47
76
|
"simple-get": "^4.0.1",
|
|
48
|
-
"snazzy": "^9.0.0",
|
|
49
77
|
"split2": "^4.2.0",
|
|
50
|
-
"standard": "^17.1.0",
|
|
51
78
|
"tap": "^18.7.2",
|
|
52
79
|
"tsd": "^0.31.0"
|
|
53
80
|
},
|
package/test/base-get.test.js
CHANGED
package/test/base-path.test.js
CHANGED
|
@@ -10,7 +10,7 @@ const instance = Fastify()
|
|
|
10
10
|
|
|
11
11
|
nock('http://httpbin.org')
|
|
12
12
|
.get('/ip')
|
|
13
|
-
.reply(200, function (
|
|
13
|
+
.reply(200, function () {
|
|
14
14
|
t.equal(this.req.headers.host, 'httpbin.org')
|
|
15
15
|
return { origin: '127.0.0.1' }
|
|
16
16
|
})
|
|
@@ -18,7 +18,7 @@ nock('http://httpbin.org')
|
|
|
18
18
|
t.plan(6)
|
|
19
19
|
t.teardown(instance.close.bind(instance))
|
|
20
20
|
|
|
21
|
-
instance.get('/', (
|
|
21
|
+
instance.get('/', (_request, reply) => {
|
|
22
22
|
reply.from('http://httpbin.org/ip')
|
|
23
23
|
})
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ t.test('use a custom instance of \'undici\'', async t => {
|
|
|
31
31
|
undici: new undici.Pool(`http://localhost:${target.address().port}`)
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
-
instance.get('/', (
|
|
34
|
+
instance.get('/', (_request, reply) => {
|
|
35
35
|
reply.from()
|
|
36
36
|
})
|
|
37
37
|
|
|
@@ -57,7 +57,7 @@ t.test('use a custom instance of \'undici\'', async t => {
|
|
|
57
57
|
undici: new undici.Client(`http://localhost:${target.address().port}`)
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
instance.get('/', (
|
|
60
|
+
instance.get('/', (_request, reply) => {
|
|
61
61
|
reply.from()
|
|
62
62
|
})
|
|
63
63
|
|
|
@@ -38,7 +38,7 @@ t.test('use a custom instance of \'undici\'', async t => {
|
|
|
38
38
|
disableRequestLogging: true
|
|
39
39
|
})
|
|
40
40
|
|
|
41
|
-
instance.get('/', (
|
|
41
|
+
instance.get('/', (_request, reply) => {
|
|
42
42
|
reply.from()
|
|
43
43
|
})
|
|
44
44
|
|
|
@@ -82,7 +82,7 @@ t.test('use a custom instance of \'undici\'', async t => {
|
|
|
82
82
|
disableRequestLogging: false
|
|
83
83
|
})
|
|
84
84
|
|
|
85
|
-
instance.get('/', (
|
|
85
|
+
instance.get('/', (_request, reply) => {
|
|
86
86
|
reply.from()
|
|
87
87
|
})
|
|
88
88
|
|
|
@@ -125,7 +125,7 @@ t.test('use a custom instance of \'undici\'', async t => {
|
|
|
125
125
|
base: `http://localhost:${target.address().port}`
|
|
126
126
|
})
|
|
127
127
|
|
|
128
|
-
instance.get('/', (
|
|
128
|
+
instance.get('/', (_request, reply) => {
|
|
129
129
|
reply.from()
|
|
130
130
|
})
|
|
131
131
|
|
|
@@ -50,7 +50,7 @@ const target = http.createServer((req, res) => {
|
|
|
50
50
|
})
|
|
51
51
|
})
|
|
52
52
|
|
|
53
|
-
instance.post('/', (
|
|
53
|
+
instance.post('/', (_request, reply) => {
|
|
54
54
|
reply.from(`http://localhost:${target.address().port}`)
|
|
55
55
|
})
|
|
56
56
|
|
|
@@ -82,7 +82,7 @@ instance.listen({ port: 0 }, (err) => {
|
|
|
82
82
|
...form.getHeaders()
|
|
83
83
|
},
|
|
84
84
|
body: form
|
|
85
|
-
}, (err,
|
|
85
|
+
}, (err, _res, data) => {
|
|
86
86
|
t.error(err)
|
|
87
87
|
t.same(JSON.parse(data), { something: 'else' })
|
|
88
88
|
})
|
|
@@ -1,47 +1,63 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const { describe, after, it } = require('node:test')
|
|
4
4
|
const fastify = require('fastify')
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
t.plan(
|
|
11
|
-
|
|
12
|
-
upstream
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
5
|
+
const fastifyProxyFrom = require('..')
|
|
6
|
+
const { isIPv6 } = require('node:net')
|
|
7
|
+
|
|
8
|
+
describe('GHSA-v2v2-hph8-q5xp', function () {
|
|
9
|
+
it('should not parse the body if it is an object', async function (t) {
|
|
10
|
+
t.plan(1)
|
|
11
|
+
|
|
12
|
+
const upstream = fastify()
|
|
13
|
+
|
|
14
|
+
upstream.post('/test', async (request) => {
|
|
15
|
+
if (typeof request.body === 'object') {
|
|
16
|
+
return 'not ok'
|
|
17
|
+
}
|
|
18
|
+
return 'ok'
|
|
19
|
+
})
|
|
18
20
|
|
|
19
|
-
upstream.listen({ port: 0 }
|
|
20
|
-
t.error(err)
|
|
21
|
+
await upstream.listen({ port: 0 })
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
app.register(From)
|
|
24
|
-
t.teardown(app.close.bind(app))
|
|
23
|
+
let upstreamAdress = upstream.server.address().address
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return reply.code(400).send({ message: 'payload contains invalid method' })
|
|
25
|
+
if (isIPv6(upstreamAdress)) {
|
|
26
|
+
upstreamAdress = `[${upstreamAdress}]`
|
|
29
27
|
}
|
|
30
|
-
reply.from(`http://127.0.0.1:${upstream.server.address().port}/test`)
|
|
31
|
-
})
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
method: 'POST'
|
|
42
|
-
}, (err, res, data) => {
|
|
43
|
-
t.error(err)
|
|
44
|
-
t.equal(data.toString(), 'ok')
|
|
29
|
+
const app = fastify()
|
|
30
|
+
app.register(fastifyProxyFrom)
|
|
31
|
+
|
|
32
|
+
app.post('/test', (request, reply) => {
|
|
33
|
+
if (request.body.method === 'invalid_method') {
|
|
34
|
+
return reply.code(400).send({ message: 'payload contains invalid method' })
|
|
35
|
+
}
|
|
36
|
+
reply.from(`http://${upstreamAdress}:${upstream.server.address().port}/test`)
|
|
45
37
|
})
|
|
38
|
+
|
|
39
|
+
await app.listen({ port: 0 })
|
|
40
|
+
|
|
41
|
+
after(() => {
|
|
42
|
+
upstream.close()
|
|
43
|
+
app.close()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
let appAddress = app.server.address().address
|
|
47
|
+
|
|
48
|
+
if (isIPv6(appAddress)) {
|
|
49
|
+
appAddress = `[${appAddress}]`
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const response = await fetch(
|
|
53
|
+
`http://${appAddress}:${app.server.address().port}/test`,
|
|
54
|
+
{
|
|
55
|
+
headers: { 'content-type': 'application/json ; charset=utf-8' },
|
|
56
|
+
// eslint-disable-next-line no-useless-escape
|
|
57
|
+
body: '"{\\\"method\\\":\\\"invalid_method\\\"}"',
|
|
58
|
+
method: 'POST'
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
t.assert.strictEqual(await response.text(), 'ok')
|
|
46
62
|
})
|
|
47
63
|
})
|
|
@@ -14,14 +14,14 @@ test('http -> http2', async function (t) {
|
|
|
14
14
|
http2: true
|
|
15
15
|
})
|
|
16
16
|
|
|
17
|
-
target.delete('/', (
|
|
17
|
+
target.delete('/', (_request, reply) => {
|
|
18
18
|
t.pass('request proxied')
|
|
19
19
|
reply.code(200).header('x-my-header', 'hello!').send({
|
|
20
20
|
hello: 'world'
|
|
21
21
|
})
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
-
instance.delete('/', (
|
|
24
|
+
instance.delete('/', (_request, reply) => {
|
|
25
25
|
reply.from()
|
|
26
26
|
})
|
|
27
27
|
|
|
@@ -14,7 +14,7 @@ instance.register(From, {
|
|
|
14
14
|
t.plan(8)
|
|
15
15
|
t.teardown(instance.close.bind(instance))
|
|
16
16
|
|
|
17
|
-
instance.addContentTypeParser('application/octet-stream', function (
|
|
17
|
+
instance.addContentTypeParser('application/octet-stream', function (_req, payload, done) {
|
|
18
18
|
done(null, payload)
|
|
19
19
|
})
|
|
20
20
|
|
|
@@ -37,7 +37,7 @@ const target = http.createServer((req, res) => {
|
|
|
37
37
|
})
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
instance.post('/', (
|
|
40
|
+
instance.post('/', (_request, reply) => {
|
|
41
41
|
reply.from(`http://localhost:${target.address().port}`)
|
|
42
42
|
})
|
|
43
43
|
|
|
@@ -58,7 +58,7 @@ instance.listen({ port: 0 }, (err) => {
|
|
|
58
58
|
body: JSON.stringify({
|
|
59
59
|
hello: 'world'
|
|
60
60
|
})
|
|
61
|
-
}, (err,
|
|
61
|
+
}, (err, _res, data) => {
|
|
62
62
|
t.error(err)
|
|
63
63
|
t.same(JSON.parse(data), { something: 'else' })
|
|
64
64
|
})
|