Files
SnowLuma/.pnpm-store/v11/files/eb/def8827c8d642c55b022c74ae7221e8110c8eb2e1ea4abbd5aceb279ab55d5e13e9e00a5b50748115d6f8444eac64730d4215608d797d6641e445c2633f44f
T
TanTan 2a69b23b47
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

257 lines
7.7 KiB
Plaintext

# Socks5ProxyAgent
<!--introduced_in=v7.23.0-->
<!--type=module-->
<!-- source_link=lib/dispatcher/socks5-proxy-agent.js -->
> Stability: 1 - Experimental
A [`Dispatcher`][] implementation that routes requests through a [SOCKS5][]
proxy server. It tunnels both HTTP and HTTPS traffic over the proxy, supports
optional username/password authentication, and pools connections per origin so
that subsequent requests to the same host reuse the established tunnel.
DNS resolution is delegated to the proxy: target host names are sent to the
proxy as domain names rather than being resolved locally. For HTTPS targets the
TLS session is negotiated end-to-end through the tunnel, so the proxy only sees
encrypted bytes.
Import it from `'undici'`:
```mjs
import { Socks5ProxyAgent } from 'undici'
```
Constructing the agent emits a one-time `ExperimentalWarning`, reflecting the
experimental status of SOCKS5 support.
## Class: `Socks5ProxyAgent`
<!-- YAML
added: v7.23.0
-->
> Stability: 1 - Experimental
* Extends: {Dispatcher}
Routes dispatched requests through a SOCKS5 proxy. Register an instance as the
global dispatcher with [`setGlobalDispatcher()`][], or pass it per request via
the `dispatcher` option.
### `new Socks5ProxyAgent(proxyUrl[, options])`
<!-- YAML
added: v7.23.0
-->
> Stability: 1 - Experimental
* `proxyUrl` {string|URL} The SOCKS5 proxy server URL. Must use the `socks5:` or
`socks:` protocol. Credentials may be embedded in the URL userinfo (for
example `socks5://user:pass@host:1080`).
* `options` {Object} (optional) Extends {PoolOptions}; the pool options are
applied to the per-origin pools created behind the tunnel.
* `headers` {Object} Additional headers to send with the proxy connection.
**Default:** `{}`.
* `username` {string} Username for SOCKS5 authentication. Takes precedence over
a username embedded in `proxyUrl`. **Default:** the URL username, if any.
* `password` {string} Password for SOCKS5 authentication. Takes precedence over
a password embedded in `proxyUrl`. **Default:** the URL password, if any.
* `connect` {Function} Custom connector used to open the socket to the proxy.
**Default:** a connector built from `proxyTls`.
* `connectTimeout` {number} Maximum time in milliseconds for each proxy
connection, SOCKS5 negotiation, and target TLS negotiation stage. A value of
`0` disables these stage timeouts. `proxyTls.timeout` and
`requestTls.timeout` override it for their respective TLS stages.
**Default:** `5000`.
* `proxyTls` {BuildOptions} TLS options for the connection to the proxy itself
(SOCKS5 over TLS). When set, the proxy connection is established over TLS and
`servername` defaults to the proxy host name.
* `requestTls` {BuildOptions} TLS options applied to the end-to-end connection
to an HTTPS target through the tunnel, such as `ca`, `cert`, `key`,
`rejectUnauthorized`, and `servername`. `servername` defaults to the target
host name.
Throws an `InvalidArgumentError` if `proxyUrl` is missing or does not use the
`socks5:` or `socks:` protocol, or if `connectTimeout`, `proxyTls.timeout`, or
`requestTls.timeout` is not a finite, non-negative number.
```mjs
import { Socks5ProxyAgent } from 'undici'
// Without authentication.
const agent = new Socks5ProxyAgent('socks5://localhost:1080')
// With credentials in the URL.
const authAgent = new Socks5ProxyAgent('socks5://user:pass@localhost:1080')
// With credentials and pool options.
const configuredAgent = new Socks5ProxyAgent('socks5://localhost:1080', {
username: 'user',
password: 'pass',
connections: 10
})
```
Using the agent as the global dispatcher:
```mjs
import { setGlobalDispatcher, request, Socks5ProxyAgent } from 'undici'
const agent = new Socks5ProxyAgent('socks5://localhost:1080')
setGlobalDispatcher(agent)
const { statusCode, body } = await request('http://localhost:3000/foo')
console.log('response received', statusCode)
for await (const data of body) {
console.log('data', data.toString('utf8'))
}
```
Using the agent per request:
```mjs
import { request, Socks5ProxyAgent } from 'undici'
const agent = new Socks5ProxyAgent('socks5://localhost:1080')
const { statusCode, body } = await request('http://localhost:3000/foo', {
dispatcher: agent
})
console.log('response received', statusCode)
```
HTTPS targets are tunnelled and encrypted end-to-end:
```mjs
import { request, Socks5ProxyAgent } from 'undici'
const agent = new Socks5ProxyAgent('socks5://localhost:1080')
const { statusCode, body } = await request('https://api.example.com/data', {
dispatcher: agent
})
console.log('Response status:', statusCode)
console.log('Response data:', await body.json())
```
### `socks5ProxyAgent.close()`
<!-- YAML
added: v7.23.0
-->
> Stability: 1 - Experimental
* Returns: {Promise<void>} Resolves once every per-origin pool has been closed.
Gracefully closes the agent, waiting for all underlying pools and their
connections to drain and close before resolving.
```mjs
import { setGlobalDispatcher, Socks5ProxyAgent } from 'undici'
const agent = new Socks5ProxyAgent('socks5://localhost:1080')
setGlobalDispatcher(agent)
// ... make requests ...
await agent.close()
```
### `socks5ProxyAgent.destroy([err])`
<!-- YAML
added: v7.23.0
-->
> Stability: 1 - Experimental
* `err` {Error} (optional) The error to reject in-flight requests with.
* Returns: {Promise<void>} Resolves once every per-origin pool has been
destroyed.
Forcibly destroys the agent and all underlying connections immediately, without
waiting for in-flight requests to complete.
```mjs
import { Socks5ProxyAgent } from 'undici'
const agent = new Socks5ProxyAgent('socks5://localhost:1080')
await agent.destroy()
```
### `socks5ProxyAgent.dispatch(options, handlers)`
<!-- YAML
added: v7.23.0
-->
> Stability: 1 - Experimental
* `options` {DispatchOptions}
* `handlers` {DispatchHandler}
* Returns: {boolean} `false` if the dispatcher is busy and the request should be
retried later, otherwise `true`.
Routes a request through the SOCKS5 tunnel. The agent maintains a [`Pool`][] per
target origin; the first request to a given origin establishes the tunnel and
upgrades to TLS when the target is HTTPS, and later requests reuse the pool.
This is the lower-level entry point implementing
[`Dispatcher.dispatch(options, handlers)`][]. Prefer
[`socks5ProxyAgent.request()`][] for most use cases.
### `socks5ProxyAgent.request(options[, callback])`
<!-- YAML
added: v7.23.0
-->
> Stability: 1 - Experimental
* `options` {DispatchOptions}
* `callback` {Function} (optional)
* Returns: {Promise|void} A promise resolving to the response when `callback` is
omitted.
Performs a request through the SOCKS5 proxy. Inherited from
[`Dispatcher.request(options[, callback])`][]; see that method for the full set
of options and the shape of the resolved response.
```mjs
import { fetch, Socks5ProxyAgent } from 'undici'
const agent = new Socks5ProxyAgent('socks5://localhost:1080')
const response = await fetch('http://localhost:3000/api/users', {
dispatcher: agent
})
console.log('Response status:', response.status)
console.log('Response data:', await response.text())
```
## Debugging
SOCKS5 proxy activity can be traced with the `undici:socks5-proxy` debug scope:
```bash
NODE_DEBUG=undici:socks5-proxy node script.js
```
This logs the SOCKS5 handshake, authentication, and tunnel establishment steps.
[SOCKS5]: https://www.rfc-editor.org/rfc/rfc1928
[`Dispatcher.dispatch(options, handlers)`]: Dispatcher.md#dispatcherdispatchoptions-handler
[`Dispatcher.request(options[, callback])`]: Dispatcher.md#dispatcherrequestoptions-callback
[`Dispatcher`]: Dispatcher.md#class-dispatcher
[`Pool`]: Pool.md#class-pool
[`setGlobalDispatcher()`]: Dispatcher.md#setglobaldispatcherdispatcher
[`socks5ProxyAgent.request()`]: #socks5proxyagentrequestoptions-callback