fetch-socks
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -9,2 +9,4 @@ import { SocksProxy } from "socks"; | ||
* | ||
* If the proxies is an empty array, it will connect directly. | ||
* | ||
* @param proxies The proxy server to use or the list of proxy servers to chain. | ||
@@ -27,2 +29,4 @@ * @param tlsOpts TLS upgrade options. | ||
* | ||
* If the proxies is an empty array, it will connect directly. | ||
* | ||
* @param proxies The proxy server to use or the list of proxy servers to chain. | ||
@@ -29,0 +33,0 @@ * @param options Additional options passed to the Agent constructor. |
57
index.js
@@ -18,2 +18,4 @@ "use strict"; | ||
* | ||
* If the proxies is an empty array, it will connect directly. | ||
* | ||
* @param proxies The proxy server to use or the list of proxy servers to chain. | ||
@@ -23,32 +25,41 @@ * @param tlsOpts TLS upgrade options. | ||
function socksConnector(proxies, tlsOpts = {}) { | ||
const chain = Array.isArray(proxies) ? proxies : [proxies]; | ||
const { timeout = 10e3 } = tlsOpts; | ||
const tlsUpgrade = (0, undici_1.buildConnector)(tlsOpts); | ||
const undiciConnect = (0, undici_1.buildConnector)(tlsOpts); | ||
return async (options, callback) => { | ||
const { protocol, hostname, port } = options; | ||
const socksOptions = { | ||
command: "connect", | ||
timeout, | ||
destination: { | ||
let { protocol, hostname, port, httpSocket } = options; | ||
for (let i = 0; i < chain.length; i++) { | ||
const next = chain[i + 1]; | ||
const destination = i === chain.length - 1 ? { | ||
host: hostname, | ||
port: resolvePort(protocol, port), | ||
}, | ||
}; | ||
const onEstablished = (error, connection) => { | ||
if (error) { | ||
} : { | ||
port: next.port, | ||
host: next.host ?? next.ipaddress, | ||
}; | ||
const socksOpts = { | ||
command: "connect", | ||
proxy: chain[i], | ||
timeout, | ||
destination, | ||
existing_socket: httpSocket, | ||
}; | ||
try { | ||
const r = await socks_1.SocksClient.createConnection(socksOpts); | ||
httpSocket = r.socket; | ||
} | ||
catch (error) { | ||
return callback(error, null); | ||
} | ||
const { socket } = connection; | ||
if (protocol !== "https:") { | ||
return callback(null, socket.setNoDelay()); | ||
} | ||
return tlsUpgrade({ ...options, httpSocket: socket }, callback); | ||
}; | ||
if (Array.isArray(proxies)) { | ||
// noinspection ES6MissingAwait | ||
socks_1.SocksClient.createConnectionChain({ proxies, ...socksOptions }, onEstablished); | ||
} | ||
else { | ||
// noinspection ES6MissingAwait | ||
socks_1.SocksClient.createConnection({ proxy: proxies, ...socksOptions }, onEstablished); | ||
// httpSocket may not exist when the chain is empty. | ||
if (httpSocket && protocol !== "https:") { | ||
return callback(null, httpSocket.setNoDelay()); | ||
} | ||
/* | ||
* There are 2 cases here: | ||
* If httpSocket doesn't exist, let undici make a connection. | ||
* If httpSocket exists & protocol is HTTPS, do TLS upgrade. | ||
*/ | ||
return undiciConnect({ ...options, httpSocket }, callback); | ||
}; | ||
@@ -60,2 +71,4 @@ } | ||
* | ||
* If the proxies is an empty array, it will connect directly. | ||
* | ||
* @param proxies The proxy server to use or the list of proxy servers to chain. | ||
@@ -62,0 +75,0 @@ * @param options Additional options passed to the Agent constructor. |
{ | ||
"name": "fetch-socks", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Socks proxy for Node builtin `fetch`", | ||
"license": "MIT", | ||
"author": "Kaciras <Kaciras@outlook.com>", | ||
"repository": { | ||
@@ -24,3 +25,3 @@ "type": "git", | ||
"socks": "^2.7.1", | ||
"undici": "^5.13.0" | ||
"undici": "^5.14.0" | ||
}, | ||
@@ -30,9 +31,9 @@ "devDependencies": { | ||
"@jest/globals": "^29.3.1", | ||
"@kaciras/eslint-config-core": "^2.4.1", | ||
"@kaciras/eslint-config-typescript": "^2.4.1", | ||
"eslint": "^8.28.0", | ||
"@kaciras/eslint-config-core": "^2.5.0", | ||
"@kaciras/eslint-config-typescript": "^2.5.0", | ||
"eslint": "^8.29.0", | ||
"jest": "^29.3.1", | ||
"mockttp": "^3.6.1", | ||
"ts-jest": "^29.0.3", | ||
"typescript": "^4.9.3" | ||
"typescript": "^4.9.4" | ||
}, | ||
@@ -39,0 +40,0 @@ "scripts": { |
@@ -26,3 +26,3 @@ # fetch-socks | ||
const response = await fetch("https://example.com", { dispatcher }); | ||
const response = await fetch("http://example.com", { dispatcher }); | ||
console.log(response.status); | ||
@@ -59,1 +59,32 @@ console.log(await response.text()); | ||
``` | ||
create a socks connection over HTTP tunnel with `socksConnector`. | ||
```javascript | ||
import { Client, Agent } from "undici"; | ||
import { socksConnector } from "fetch-socks"; | ||
const socksConnect = socksConnector({ | ||
type: 5, | ||
host: "::1", | ||
port: 1080, | ||
}); | ||
async function connect(options, callback) { | ||
// First establish a connection to the HTTP proxy server (localhost:80). | ||
const client = new Client("http://localhost:80"); | ||
const { socket, statusCode } = await client.connect({ | ||
// Tell the server to connect to the next ([::1]:1080) | ||
path: "[::1]:1080", | ||
}); | ||
if (statusCode !== 200) { | ||
callback(new Error("Proxy response !== 200 when HTTP Tunneling")); | ||
} else { | ||
// Perform socks handshake on the connection. | ||
socksConnect({ ...options, httpSocket: socket }, callback); | ||
} | ||
} | ||
const dispatcher = new Agent({ connect }); | ||
const response = await fetch("https://example.com", { dispatcher }); | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
8812
111
1
89
Updatedundici@^5.14.0