Skip to content

Commit fe00bec

Browse files
nodejs-github-bottargos
authored andcommitted
deps: update undici to 6.16.1
PR-URL: #52948 Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent ee56aec commit fe00bec

29 files changed

Lines changed: 1028 additions & 589 deletions
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# Class: EnvHttpProxyAgent
2+
3+
Stability: Experimental.
4+
5+
Extends: `undici.Dispatcher`
6+
7+
EnvHttpProxyAgent automatically reads the proxy configuration from the environment variables `http_proxy`, `https_proxy`, and `no_proxy` and sets up the proxy agents accordingly. When `http_proxy` and `https_proxy` are set, `http_proxy` is used for HTTP requests and `https_proxy` is used for HTTPS requests. If only `http_proxy` is set, `http_proxy` is used for both HTTP and HTTPS requests. If only `https_proxy` is set, it is only used for HTTPS requests.
8+
9+
`no_proxy` is a comma or space-separated list of hostnames that should not be proxied. The list may contain leading wildcard characters (`*`). If `no_proxy` is set, the EnvHttpProxyAgent will bypass the proxy for requests to hosts that match the list. If `no_proxy` is set to `"*"`, the EnvHttpProxyAgent will bypass the proxy for all requests.
10+
11+
Uppercase environment variables are also supported: `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. However, if both the lowercase and uppercase environment variables are set, the uppercase environment variables will be ignored.
12+
13+
## `new EnvHttpProxyAgent([options])`
14+
15+
Arguments:
16+
17+
***options**`EnvHttpProxyAgentOptions` (optional) - extends the `Agent` options.
18+
19+
Returns: `EnvHttpProxyAgent`
20+
21+
### Parameter: `EnvHttpProxyAgentOptions`
22+
23+
Extends: [`AgentOptions`](Agent.md#parameter-agentoptions)
24+
25+
***httpProxy**`string` (optional) - When set, it will override the `HTTP_PROXY` environment variable.
26+
***httpsProxy**`string` (optional) - When set, it will override the `HTTPS_PROXY` environment variable.
27+
***noProxy**`string` (optional) - When set, it will override the `NO_PROXY` environment variable.
28+
29+
Examples:
30+
31+
```js
32+
import { EnvHttpProxyAgent } from'undici'
33+
34+
constenvHttpProxyAgent=newEnvHttpProxyAgent()
35+
// or
36+
constenvHttpProxyAgent=newEnvHttpProxyAgent({ httpProxy:'my.proxy.server:8080', httpsProxy:'my.proxy.server:8443', noProxy:'localhost' })
37+
```
38+
39+
#### Example - EnvHttpProxyAgent instantiation
40+
41+
This will instantiate the EnvHttpProxyAgent. It will not do anything until registered as the agent to use with requests.
42+
43+
```js
44+
import { EnvHttpProxyAgent } from'undici'
45+
46+
constenvHttpProxyAgent=newEnvHttpProxyAgent()
47+
```
48+
49+
#### Example - Basic Proxy Fetch with global agent dispatcher
50+
51+
```js
52+
import { setGlobalDispatcher, fetch, EnvHttpProxyAgent } from'undici'
53+
54+
constenvHttpProxyAgent=newEnvHttpProxyAgent()
55+
setGlobalDispatcher(envHttpProxyAgent)
56+
57+
const { status, json } =awaitfetch('http://localhost:3000/foo')
58+
59+
console.log('response received', status) // response received 200
60+
61+
constdata=awaitjson() // data { foo: "bar" }
62+
```
63+
64+
#### Example - Basic Proxy Request with global agent dispatcher
65+
66+
```js
67+
import { setGlobalDispatcher, request, EnvHttpProxyAgent } from'undici'
68+
69+
constenvHttpProxyAgent=newEnvHttpProxyAgent()
70+
setGlobalDispatcher(envHttpProxyAgent)
71+
72+
const { statusCode, body } =awaitrequest('http://localhost:3000/foo')
73+
74+
console.log('response received', statusCode) // response received 200
75+
76+
forawait (constdataofbody) {
77+
console.log('data', data.toString('utf8')) // data foo
78+
}
79+
```
80+
81+
#### Example - Basic Proxy Request with local agent dispatcher
82+
83+
```js
84+
import { EnvHttpProxyAgent, request } from'undici'
85+
86+
constenvHttpProxyAgent=newEnvHttpProxyAgent()
87+
88+
const {
89+
statusCode,
90+
body
91+
} =awaitrequest('http://localhost:3000/foo', { dispatcher: envHttpProxyAgent })
92+
93+
console.log('response received', statusCode) // response received 200
94+
95+
forawait (constdataofbody) {
96+
console.log('data', data.toString('utf8')) // data foo
97+
}
98+
```
99+
100+
#### Example - Basic Proxy Fetch with local agent dispatcher
101+
102+
```js
103+
import { EnvHttpProxyAgent, fetch } from'undici'
104+
105+
constenvHttpProxyAgent=newEnvHttpProxyAgent()
106+
107+
const {
108+
status,
109+
json
110+
} =awaitfetch('http://localhost:3000/foo', { dispatcher: envHttpProxyAgent })
111+
112+
console.log('response received', status) // response received 200
113+
114+
constdata=awaitjson() // data { foo: "bar" }
115+
```
116+
117+
## Instance Methods
118+
119+
### `EnvHttpProxyAgent.close([callback])`
120+
121+
Implements [`Dispatcher.close([callback])`](Dispatcher.md#dispatcherclosecallback-promise).
122+
123+
### `EnvHttpProxyAgent.destroy([error, callback])`
124+
125+
Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).
126+
127+
### `EnvHttpProxyAgent.dispatch(options, handler: AgentDispatchOptions)`
128+
129+
Implements [`Dispatcher.dispatch(options, handler)`](Dispatcher.md#dispatcherdispatchoptions-handler).
130+
131+
#### Parameter: `AgentDispatchOptions`
132+
133+
Extends: [`DispatchOptions`](Dispatcher.md#parameter-dispatchoptions)
134+
135+
***origin**`string | URL`
136+
***maxRedirections**`Integer`.
137+
138+
Implements [`Dispatcher.destroy([error, callback])`](Dispatcher.md#dispatcherdestroyerror-callback-promise).
139+
140+
### `EnvHttpProxyAgent.connect(options[, callback])`
141+
142+
See [`Dispatcher.connect(options[, callback])`](Dispatcher.md#dispatcherconnectoptions-callback).
143+
144+
### `EnvHttpProxyAgent.dispatch(options, handler)`
145+
146+
Implements [`Dispatcher.dispatch(options, handler)`](Dispatcher.md#dispatcherdispatchoptions-handler).
147+
148+
### `EnvHttpProxyAgent.pipeline(options, handler)`
149+
150+
See [`Dispatcher.pipeline(options, handler)`](Dispatcher.md#dispatcherpipelineoptions-handler).
151+
152+
### `EnvHttpProxyAgent.request(options[, callback])`
153+
154+
See [`Dispatcher.request(options [, callback])`](Dispatcher.md#dispatcherrequestoptions-callback).
155+
156+
### `EnvHttpProxyAgent.stream(options, factory[, callback])`
157+
158+
See [`Dispatcher.stream(options, factory[, callback])`](Dispatcher.md#dispatcherstreamoptions-factory-callback).
159+
160+
### `EnvHttpProxyAgent.upgrade(options[, callback])`
161+
162+
See [`Dispatcher.upgrade(options[, callback])`](Dispatcher.md#dispatcherupgradeoptions-callback).

‎deps/undici/src/docs/docs/api/Util.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ Receives a header object and returns the parsed value.
88

99
Arguments:
1010

11-
-**headers**`Record<string, string | string[]> | (Buffer | string | (Buffer | string)[])[]` (required) - Header object.
11+
-**headers**`(Buffer | string | (Buffer | string)[])[]` (required) - Header object.
1212

1313
-**obj**`Record<string, string | string[]>` (optional) - Object to specify a proxy object. The parsed value is assigned to this object. But, if **headers** is an object, it is not used.
1414

15-
Returns: `Record<string, string | string[]>` If **headers** is an object, it is **headers**. Otherwise, if **obj** is specified, it is equivalent to **obj**.
15+
Returns: `Record<string, string | string[]>` If **obj** is specified, it is equivalent to **obj**.
1616

1717
## `headerNameToString(value)`
1818

‎deps/undici/src/docs/docs/best-practices/proxy.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Connecting through a proxy is possible by:
44

5-
- Using [AgentProxy](../api/ProxyAgent.md).
5+
- Using [ProxyAgent](../api/ProxyAgent.md).
66
- Configuring `Client` or `Pool` constructor.
77

88
The proxy url should be passed to the `Client` or `Pool` constructor, while the upstream server url

‎deps/undici/src/lib/api/api-request.js‎

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
constassert=require('node:assert')
44
const{ Readable }=require('./readable')
5-
const{ InvalidArgumentError }=require('../core/errors')
5+
const{ InvalidArgumentError, RequestAbortedError}=require('../core/errors')
66
constutil=require('../core/util')
77
const{ getResolveErrorBodyCallback }=require('./util')
88
const{ AsyncResource }=require('node:async_hooks')
9-
const{ addSignal, removeSignal }=require('./abort-signal')
109

1110
classRequestHandlerextendsAsyncResource{
1211
constructor(opts,callback){
@@ -45,6 +44,7 @@ class RequestHandler extends AsyncResource {
4544
throwerr
4645
}
4746

47+
this.method=method
4848
this.responseHeaders=responseHeaders||null
4949
this.opaque=opaque||null
5050
this.callback=callback
@@ -56,14 +56,36 @@ class RequestHandler extends AsyncResource {
5656
this.onInfo=onInfo||null
5757
this.throwOnError=throwOnError
5858
this.highWaterMark=highWaterMark
59+
this.signal=signal
60+
this.reason=null
61+
this.removeAbortListener=null
5962

6063
if(util.isStream(body)){
6164
body.on('error',(err)=>{
6265
this.onError(err)
6366
})
6467
}
6568

66-
addSignal(this,signal)
69+
if(this.signal){
70+
if(this.signal.aborted){
71+
this.reason=this.signal.reason??newRequestAbortedError()
72+
}else{
73+
this.removeAbortListener=util.addAbortListener(this.signal,()=>{
74+
this.reason=this.signal.reason??newRequestAbortedError()
75+
if(this.res){
76+
util.destroy(this.res,this.reason)
77+
}elseif(this.abort){
78+
this.abort(this.reason)
79+
}
80+
81+
if(this.removeAbortListener){
82+
this.res?.off('close',this.removeAbortListener)
83+
this.removeAbortListener()
84+
this.removeAbortListener=null
85+
}
86+
})
87+
}
88+
}
6789
}
6890

6991
onConnect(abort,context){
@@ -93,48 +115,52 @@ class RequestHandler extends AsyncResource {
93115
constparsedHeaders=responseHeaders==='raw' ? util.parseHeaders(rawHeaders) : headers
94116
constcontentType=parsedHeaders['content-type']
95117
constcontentLength=parsedHeaders['content-length']
96-
constbody=newReadable({ resume, abort, contentType, contentLength, highWaterMark })
118+
constres=newReadable({
119+
resume,
120+
abort,
121+
contentType,
122+
contentLength: this.method!=='HEAD'&&contentLength
123+
? Number(contentLength)
124+
: null,
125+
highWaterMark
126+
})
127+
128+
if(this.removeAbortListener){
129+
res.on('close',this.removeAbortListener)
130+
}
97131

98132
this.callback=null
99-
this.res=body
133+
this.res=res
100134
if(callback!==null){
101135
if(this.throwOnError&&statusCode>=400){
102136
this.runInAsyncScope(getResolveErrorBodyCallback,null,
103-
{ callback, body, contentType, statusCode, statusMessage, headers }
137+
{ callback,body: res, contentType, statusCode, statusMessage, headers }
104138
)
105139
}else{
106140
this.runInAsyncScope(callback,null,null,{
107141
statusCode,
108142
headers,
109143
trailers: this.trailers,
110144
opaque,
111-
body,
145+
body: res,
112146
context
113147
})
114148
}
115149
}
116150
}
117151

118152
onData(chunk){
119-
const{ res }=this
120-
returnres.push(chunk)
153+
returnthis.res.push(chunk)
121154
}
122155

123156
onComplete(trailers){
124-
const{ res }=this
125-
126-
removeSignal(this)
127-
128157
util.parseHeaders(trailers,this.trailers)
129-
130-
res.push(null)
158+
this.res.push(null)
131159
}
132160

133161
onError(err){
134162
const{ res, callback, body, opaque }=this
135163

136-
removeSignal(this)
137-
138164
if(callback){
139165
// TODO: Does this need queueMicrotask?
140166
this.callback=null
@@ -155,6 +181,12 @@ class RequestHandler extends AsyncResource {
155181
this.body=null
156182
util.destroy(body,err)
157183
}
184+
185+
if(this.removeAbortListener){
186+
res?.off('close',this.removeAbortListener)
187+
this.removeAbortListener()
188+
this.removeAbortListener=null
189+
}
158190
}
159191
}
160192

‎deps/undici/src/lib/api/readable.js‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,13 @@ class BodyReadable extends Readable {
6363
// tick as it is created, then a user who is waiting for a
6464
// promise (i.e micro tick) for installing a 'error' listener will
6565
// never get a chance and will always encounter an unhandled exception.
66-
setImmediate(()=>{
66+
if(!this[kReading]){
67+
setImmediate(()=>{
68+
callback(err)
69+
})
70+
}else{
6771
callback(err)
68-
})
72+
}
6973
}
7074

7175
on(ev, ...args){

‎deps/undici/src/lib/core/connect.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ function setupTimeout (onConnectTimeout, timeout) {
165165
lets1=null
166166
lets2=null
167167
consttimeoutId=setTimeout(()=>{
168-
// setImmediate is added to make sure that we priotorise socket error events over timeouts
168+
// setImmediate is added to make sure that we prioritize socket error events over timeouts
169169
s1=setImmediate(()=>{
170170
if(process.platform==='win32'){
171171
// Windows needs an extra setImmediate probably due to implementation differences in the socket logic

‎deps/undici/src/lib/dispatcher/client-h2.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ function writeH2 (client, request) {
524524
}
525525
}elseif(util.isStream(body)){
526526
writeStream({
527+
abort,
527528
body,
528529
client,
529530
request,
@@ -535,6 +536,7 @@ function writeH2 (client, request) {
535536
})
536537
}elseif(util.isIterable(body)){
537538
writeIterable({
539+
abort,
538540
body,
539541
client,
540542
request,

0 commit comments

Comments
 (0)