feat: 초기 프로젝트 설정 및 룰.md 파일 추가

This commit is contained in:
2025-07-28 09:53:31 +09:00
commit 09a4d38512
8165 changed files with 1021855 additions and 0 deletions

87
api.hyungi.net/node_modules/proxy-agent/README.md generated vendored Normal file
View File

@@ -0,0 +1,87 @@
proxy-agent
===========
### Maps proxy protocols to `http.Agent` implementations
This module provides an `http.Agent` implementation which automatically uses
proxy servers based off of the various proxy-related environment variables
(`HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` among others).
Which proxy is used for each HTTP request is determined by the
[`proxy-from-env`](https://www.npmjs.com/package/proxy-from-env) module, so
check its documentation for instructions on configuring your environment variables.
An LRU cache is used so that `http.Agent` instances are transparently re-used for
subsequent HTTP requests to the same proxy server.
The currently implemented protocol mappings are listed in the table below:
| Protocol | Proxy Agent for `http` requests | Proxy Agent for `https` requests | Example
|:----------:|:-------------------------------:|:--------------------------------:|:--------:
| `http` | [http-proxy-agent][] | [https-proxy-agent][] | `http://proxy-server-over-tcp.com:3128`
| `https` | [http-proxy-agent][] | [https-proxy-agent][] | `https://proxy-server-over-tls.com:3129`
| `socks(v5)`| [socks-proxy-agent][] | [socks-proxy-agent][] | `socks://username:password@some-socks-proxy.com:9050` (username & password are optional)
| `socks5` | [socks-proxy-agent][] | [socks-proxy-agent][] | `socks5://username:password@some-socks-proxy.com:9050` (username & password are optional)
| `socks4` | [socks-proxy-agent][] | [socks-proxy-agent][] | `socks4://some-socks-proxy.com:9050`
| `pac-*` | [pac-proxy-agent][] | [pac-proxy-agent][] | `pac+http://www.example.com/proxy.pac`
Example
-------
```ts
import * as https from 'https';
import { ProxyAgent } from 'proxy-agent';
// The correct proxy `Agent` implementation to use will be determined
// via the `http_proxy` / `https_proxy` / `no_proxy` / etc. env vars
const agent = new ProxyAgent();
// The rest works just like any other normal HTTP request
https.get('https://jsonip.com', { agent }, (res) => {
console.log(res.statusCode, res.headers);
res.pipe(process.stdout);
});
```
API
---
### new ProxyAgent(options?: ProxyAgentOptions)
Creates an `http.Agent` instance which relies on the various proxy-related
environment variables. An LRU cache is used, so the same `http.Agent` instance
will be returned if identical args are passed in.
License
-------
(The MIT License)
Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[http-proxy-agent]: ../http-proxy-agent
[https-proxy-agent]: ../https-proxy-agent
[socks-proxy-agent]: ../socks-proxy-agent
[pac-proxy-agent]: ../pac-proxy-agent

View File

@@ -0,0 +1,60 @@
/// <reference types="node" />
import * as http from 'http';
import LRUCache from 'lru-cache';
import { Agent, AgentConnectOpts } from 'agent-base';
import { PacProxyAgentOptions } from 'pac-proxy-agent';
import { HttpProxyAgentOptions } from 'http-proxy-agent';
import { HttpsProxyAgentOptions } from 'https-proxy-agent';
import { SocksProxyAgentOptions } from 'socks-proxy-agent';
declare const PROTOCOLS: readonly ["http", "https", "socks", "socks4", "socks4a", "socks5", "socks5h", ...("pac+http" | "pac+https" | "pac+data" | "pac+file" | "pac+ftp")[]];
type ValidProtocol = (typeof PROTOCOLS)[number];
type AgentConstructor = new (...args: never[]) => Agent;
type GetProxyForUrlCallback = (url: string) => string;
/**
* Supported proxy types.
*/
export declare const proxies: {
[P in ValidProtocol]: [AgentConstructor, AgentConstructor];
};
export type ProxyAgentOptions = HttpProxyAgentOptions<''> & HttpsProxyAgentOptions<''> & SocksProxyAgentOptions & PacProxyAgentOptions<''> & {
/**
* Default `http.Agent` instance to use when no proxy is
* configured for a request. Defaults to a new `http.Agent()`
* instance with the proxy agent options passed in.
*/
httpAgent?: http.Agent;
/**
* Default `http.Agent` instance to use when no proxy is
* configured for a request. Defaults to a new `https.Agent()`
* instance with the proxy agent options passed in.
*/
httpsAgent?: http.Agent;
/**
* A callback for dynamic provision of proxy for url.
* Defaults to standard proxy environment variables,
* see https://www.npmjs.com/package/proxy-from-env for details
*/
getProxyForUrl?: GetProxyForUrlCallback;
};
/**
* Uses the appropriate `Agent` subclass based off of the "proxy"
* environment variables that are currently set.
*
* An LRU cache is used, to prevent unnecessary creation of proxy
* `http.Agent` instances.
*/
export declare class ProxyAgent extends Agent {
/**
* Cache for `Agent` instances.
*/
cache: LRUCache<string, Agent>;
connectOpts?: ProxyAgentOptions;
httpAgent: http.Agent;
httpsAgent: http.Agent;
getProxyForUrl: GetProxyForUrlCallback;
constructor(opts?: ProxyAgentOptions);
connect(req: http.ClientRequest, opts: AgentConnectOpts): Promise<http.Agent>;
destroy(): void;
}
export {};
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,EAAiB,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAkB,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAmB,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAmB,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAI5E,QAAA,MAAM,SAAS,sJAIL,CAAC;AAEX,KAAK,aAAa,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD,KAAK,gBAAgB,GAAG,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,CAAC;AAExD,KAAK,sBAAsB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;AAEtD;;GAEG;AACH,eAAO,MAAM,OAAO,EAAE;KACpB,CAAC,IAAI,aAAa,GAAG,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;CAc1D,CAAC;AAMF,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,EAAE,CAAC,GACxD,sBAAsB,CAAC,EAAE,CAAC,GAC1B,sBAAsB,GACtB,oBAAoB,CAAC,EAAE,CAAC,GAAG;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;IACvB;;;;OAIG;IACH,UAAU,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;IACxB;;;;OAIG;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACxC,CAAC;AAEH;;;;;;GAMG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACpC;;OAEG;IACH,KAAK,0BAA4C;IAEjD,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;IACtB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC;IACvB,cAAc,EAAE,sBAAsB,CAAC;gBAE3B,IAAI,CAAC,EAAE,iBAAiB;IAU9B,OAAO,CACZ,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,IAAI,EAAE,gBAAgB,GACpB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;IA2CtB,OAAO,IAAI,IAAI;CAMf"}

134
api.hyungi.net/node_modules/proxy-agent/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,134 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProxyAgent = exports.proxies = void 0;
const http = __importStar(require("http"));
const https = __importStar(require("https"));
const url_1 = require("url");
const lru_cache_1 = __importDefault(require("lru-cache"));
const agent_base_1 = require("agent-base");
const debug_1 = __importDefault(require("debug"));
const proxy_from_env_1 = require("proxy-from-env");
const pac_proxy_agent_1 = require("pac-proxy-agent");
const http_proxy_agent_1 = require("http-proxy-agent");
const https_proxy_agent_1 = require("https-proxy-agent");
const socks_proxy_agent_1 = require("socks-proxy-agent");
const debug = (0, debug_1.default)('proxy-agent');
const PROTOCOLS = [
...http_proxy_agent_1.HttpProxyAgent.protocols,
...socks_proxy_agent_1.SocksProxyAgent.protocols,
...pac_proxy_agent_1.PacProxyAgent.protocols,
];
/**
* Supported proxy types.
*/
exports.proxies = {
http: [http_proxy_agent_1.HttpProxyAgent, https_proxy_agent_1.HttpsProxyAgent],
https: [http_proxy_agent_1.HttpProxyAgent, https_proxy_agent_1.HttpsProxyAgent],
socks: [socks_proxy_agent_1.SocksProxyAgent, socks_proxy_agent_1.SocksProxyAgent],
socks4: [socks_proxy_agent_1.SocksProxyAgent, socks_proxy_agent_1.SocksProxyAgent],
socks4a: [socks_proxy_agent_1.SocksProxyAgent, socks_proxy_agent_1.SocksProxyAgent],
socks5: [socks_proxy_agent_1.SocksProxyAgent, socks_proxy_agent_1.SocksProxyAgent],
socks5h: [socks_proxy_agent_1.SocksProxyAgent, socks_proxy_agent_1.SocksProxyAgent],
'pac+data': [pac_proxy_agent_1.PacProxyAgent, pac_proxy_agent_1.PacProxyAgent],
'pac+file': [pac_proxy_agent_1.PacProxyAgent, pac_proxy_agent_1.PacProxyAgent],
'pac+ftp': [pac_proxy_agent_1.PacProxyAgent, pac_proxy_agent_1.PacProxyAgent],
'pac+http': [pac_proxy_agent_1.PacProxyAgent, pac_proxy_agent_1.PacProxyAgent],
'pac+https': [pac_proxy_agent_1.PacProxyAgent, pac_proxy_agent_1.PacProxyAgent],
};
function isValidProtocol(v) {
return PROTOCOLS.includes(v);
}
/**
* Uses the appropriate `Agent` subclass based off of the "proxy"
* environment variables that are currently set.
*
* An LRU cache is used, to prevent unnecessary creation of proxy
* `http.Agent` instances.
*/
class ProxyAgent extends agent_base_1.Agent {
constructor(opts) {
super(opts);
/**
* Cache for `Agent` instances.
*/
this.cache = new lru_cache_1.default({ max: 20 });
debug('Creating new ProxyAgent instance: %o', opts);
this.connectOpts = opts;
this.httpAgent = opts?.httpAgent || new http.Agent(opts);
this.httpsAgent =
opts?.httpsAgent || new https.Agent(opts);
this.getProxyForUrl = opts?.getProxyForUrl || proxy_from_env_1.getProxyForUrl;
}
async connect(req, opts) {
const { secureEndpoint } = opts;
const isWebSocket = req.getHeader('upgrade') === 'websocket';
const protocol = secureEndpoint
? isWebSocket
? 'wss:'
: 'https:'
: isWebSocket
? 'ws:'
: 'http:';
const host = req.getHeader('host');
const url = new url_1.URL(req.path, `${protocol}//${host}`).href;
const proxy = this.getProxyForUrl(url);
if (!proxy) {
debug('Proxy not enabled for URL: %o', url);
return secureEndpoint ? this.httpsAgent : this.httpAgent;
}
debug('Request URL: %o', url);
debug('Proxy URL: %o', proxy);
// attempt to get a cached `http.Agent` instance first
const cacheKey = `${protocol}+${proxy}`;
let agent = this.cache.get(cacheKey);
if (!agent) {
const proxyUrl = new url_1.URL(proxy);
const proxyProto = proxyUrl.protocol.replace(':', '');
if (!isValidProtocol(proxyProto)) {
throw new Error(`Unsupported protocol for proxy URL: ${proxy}`);
}
const ctor = exports.proxies[proxyProto][secureEndpoint || isWebSocket ? 1 : 0];
// @ts-expect-error meh…
agent = new ctor(proxy, this.connectOpts);
this.cache.set(cacheKey, agent);
}
else {
debug('Cache hit for proxy URL: %o', proxy);
}
return agent;
}
destroy() {
for (const agent of this.cache.values()) {
agent.destroy();
}
super.destroy();
}
}
exports.ProxyAgent = ProxyAgent;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,69 @@
agent-base
==========
### Turn a function into an [`http.Agent`][http.Agent] instance
This module is a thin wrapper around the base `http.Agent` class.
It provides an abstract class that must define a `connect()` function,
which is responsible for creating the underlying socket that the HTTP
client requests will use.
The `connect()` function may return an arbitrary `Duplex` stream, or
another `http.Agent` instance to delegate the request to, and may be
asynchronous (by defining an `async` function).
Instances of this agent can be used with the `http` and `https`
modules. To differentiate, the options parameter in the `connect()`
function includes a `secureEndpoint` property, which can be checked
to determine what type of socket should be returned.
#### Some subclasses:
Here are some more interesting uses of `agent-base`.
Send a pull request to list yours!
* [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints
* [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints
* [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS
* [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS
Example
-------
Here's a minimal example that creates a new `net.Socket` or `tls.Socket`
based on the `secureEndpoint` property. This agent can be used with both
the `http` and `https` modules.
```ts
import * as net from 'net';
import * as tls from 'tls';
import * as http from 'http';
import { Agent } from 'agent-base';
class MyAgent extends Agent {
connect(req, opts) {
// `secureEndpoint` is true when using the "https" module
if (opts.secureEndpoint) {
return tls.connect(opts);
} else {
return net.connect(opts);
}
}
});
// Keep alive enabled means that `connect()` will only be
// invoked when a new connection needs to be created
const agent = new MyAgent({ keepAlive: true });
// Pass the `agent` option when creating the HTTP request
http.get('http://nodejs.org/api/', { agent }, (res) => {
console.log('"response" event!', res.headers);
res.pipe(process.stdout);
});
```
[http-proxy-agent]: ../http-proxy-agent
[https-proxy-agent]: ../https-proxy-agent
[pac-proxy-agent]: ../pac-proxy-agent
[socks-proxy-agent]: ../socks-proxy-agent
[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent

View File

@@ -0,0 +1,15 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import * as http from 'http';
import * as https from 'https';
import type { Readable } from 'stream';
export type ThenableRequest = http.ClientRequest & {
then: Promise<http.IncomingMessage>['then'];
};
export declare function toBuffer(stream: Readable): Promise<Buffer>;
export declare function json(stream: Readable): Promise<any>;
export declare function req(url: string | URL, opts?: https.RequestOptions): ThenableRequest;
//# sourceMappingURL=helpers.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;;;AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,GAAG;IAClD,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;CAC5C,CAAC;AAEF,wBAAsB,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAQhE;AAGD,wBAAsB,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAUzD;AAED,wBAAgB,GAAG,CAClB,GAAG,EAAE,MAAM,GAAG,GAAG,EACjB,IAAI,GAAE,KAAK,CAAC,cAAmB,GAC7B,eAAe,CAcjB"}

View File

@@ -0,0 +1,66 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.req = exports.json = exports.toBuffer = void 0;
const http = __importStar(require("http"));
const https = __importStar(require("https"));
async function toBuffer(stream) {
let length = 0;
const chunks = [];
for await (const chunk of stream) {
length += chunk.length;
chunks.push(chunk);
}
return Buffer.concat(chunks, length);
}
exports.toBuffer = toBuffer;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function json(stream) {
const buf = await toBuffer(stream);
const str = buf.toString('utf8');
try {
return JSON.parse(str);
}
catch (_err) {
const err = _err;
err.message += ` (input: ${str})`;
throw err;
}
}
exports.json = json;
function req(url, opts = {}) {
const href = typeof url === 'string' ? url : url.href;
const req = (href.startsWith('https:') ? https : http).request(url, opts);
const promise = new Promise((resolve, reject) => {
req
.once('response', resolve)
.once('error', reject)
.end();
});
req.then = promise.then.bind(promise);
return req;
}
exports.req = req;
//# sourceMappingURL=helpers.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAC7B,6CAA+B;AAOxB,KAAK,UAAU,QAAQ,CAAC,MAAgB;IAC9C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KACnB;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC;AARD,4BAQC;AAED,8DAA8D;AACvD,KAAK,UAAU,IAAI,CAAC,MAAgB;IAC1C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;KACvB;IAAC,OAAO,IAAa,EAAE;QACvB,MAAM,GAAG,GAAG,IAAa,CAAC;QAC1B,GAAG,CAAC,OAAO,IAAI,YAAY,GAAG,GAAG,CAAC;QAClC,MAAM,GAAG,CAAC;KACV;AACF,CAAC;AAVD,oBAUC;AAED,SAAgB,GAAG,CAClB,GAAiB,EACjB,OAA6B,EAAE;IAE/B,MAAM,IAAI,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IACtD,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAC7D,GAAG,EACH,IAAI,CACe,CAAC;IACrB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrE,GAAG;aACD,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC;aACzB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;aACrB,GAAG,EAAqB,CAAC;IAC5B,CAAC,CAAC,CAAC;IACH,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,GAAG,CAAC;AACZ,CAAC;AAjBD,kBAiBC"}

View File

@@ -0,0 +1,41 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import * as net from 'net';
import * as tls from 'tls';
import * as http from 'http';
import type { Duplex } from 'stream';
export * from './helpers';
interface HttpConnectOpts extends net.TcpNetConnectOpts {
secureEndpoint: false;
protocol?: string;
}
interface HttpsConnectOpts extends tls.ConnectionOptions {
secureEndpoint: true;
protocol?: string;
port: number;
}
export type AgentConnectOpts = HttpConnectOpts | HttpsConnectOpts;
declare const INTERNAL: unique symbol;
export declare abstract class Agent extends http.Agent {
private [INTERNAL];
options: Partial<net.TcpNetConnectOpts & tls.ConnectionOptions>;
keepAlive: boolean;
constructor(opts?: http.AgentOptions);
abstract connect(req: http.ClientRequest, options: AgentConnectOpts): Promise<Duplex | http.Agent> | Duplex | http.Agent;
/**
* Determine whether this is an `http` or `https` request.
*/
isSecureEndpoint(options?: AgentConnectOpts): boolean;
private incrementSockets;
private decrementSockets;
getName(options: AgentConnectOpts): string;
createSocket(req: http.ClientRequest, options: AgentConnectOpts, cb: (err: Error | null, s?: Duplex) => void): void;
createConnection(): Duplex;
get defaultPort(): number;
set defaultPort(v: number);
get protocol(): string;
set protocol(v: string);
}
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,cAAc,WAAW,CAAC;AAE1B,UAAU,eAAgB,SAAQ,GAAG,CAAC,iBAAiB;IACtD,cAAc,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,gBAAiB,SAAQ,GAAG,CAAC,iBAAiB;IACvD,cAAc,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,gBAAgB,CAAC;AAElE,QAAA,MAAM,QAAQ,eAAmC,CAAC;AAQlD,8BAAsB,KAAM,SAAQ,IAAI,CAAC,KAAK;IAC7C,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAgB;IAGlC,OAAO,EAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACjE,SAAS,EAAG,OAAO,CAAC;gBAER,IAAI,CAAC,EAAE,IAAI,CAAC,YAAY;IAKpC,QAAQ,CAAC,OAAO,CACf,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK;IAErD;;OAEG;IACH,gBAAgB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO;IAqCrD,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM;IAa1C,YAAY,CACX,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,OAAO,EAAE,gBAAgB,EACzB,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI;IAgC5C,gBAAgB,IAAI,MAAM;IAW1B,IAAI,WAAW,IAAI,MAAM,CAKxB;IAED,IAAI,WAAW,CAAC,CAAC,EAAE,MAAM,EAIxB;IAED,IAAI,QAAQ,IAAI,MAAM,CAKrB;IAED,IAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,EAIrB;CACD"}

View File

@@ -0,0 +1,180 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Agent = void 0;
const net = __importStar(require("net"));
const http = __importStar(require("http"));
const https_1 = require("https");
__exportStar(require("./helpers"), exports);
const INTERNAL = Symbol('AgentBaseInternalState');
class Agent extends http.Agent {
constructor(opts) {
super(opts);
this[INTERNAL] = {};
}
/**
* Determine whether this is an `http` or `https` request.
*/
isSecureEndpoint(options) {
if (options) {
// First check the `secureEndpoint` property explicitly, since this
// means that a parent `Agent` is "passing through" to this instance.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (typeof options.secureEndpoint === 'boolean') {
return options.secureEndpoint;
}
// If no explicit `secure` endpoint, check if `protocol` property is
// set. This will usually be the case since using a full string URL
// or `URL` instance should be the most common usage.
if (typeof options.protocol === 'string') {
return options.protocol === 'https:';
}
}
// Finally, if no `protocol` property was set, then fall back to
// checking the stack trace of the current call stack, and try to
// detect the "https" module.
const { stack } = new Error();
if (typeof stack !== 'string')
return false;
return stack
.split('\n')
.some((l) => l.indexOf('(https.js:') !== -1 ||
l.indexOf('node:https:') !== -1);
}
// In order to support async signatures in `connect()` and Node's native
// connection pooling in `http.Agent`, the array of sockets for each origin
// has to be updated synchronously. This is so the length of the array is
// accurate when `addRequest()` is next called. We achieve this by creating a
// fake socket and adding it to `sockets[origin]` and incrementing
// `totalSocketCount`.
incrementSockets(name) {
// If `maxSockets` and `maxTotalSockets` are both Infinity then there is no
// need to create a fake socket because Node.js native connection pooling
// will never be invoked.
if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) {
return null;
}
// All instances of `sockets` are expected TypeScript errors. The
// alternative is to add it as a private property of this class but that
// will break TypeScript subclassing.
if (!this.sockets[name]) {
// @ts-expect-error `sockets` is readonly in `@types/node`
this.sockets[name] = [];
}
const fakeSocket = new net.Socket({ writable: false });
this.sockets[name].push(fakeSocket);
// @ts-expect-error `totalSocketCount` isn't defined in `@types/node`
this.totalSocketCount++;
return fakeSocket;
}
decrementSockets(name, socket) {
if (!this.sockets[name] || socket === null) {
return;
}
const sockets = this.sockets[name];
const index = sockets.indexOf(socket);
if (index !== -1) {
sockets.splice(index, 1);
// @ts-expect-error `totalSocketCount` isn't defined in `@types/node`
this.totalSocketCount--;
if (sockets.length === 0) {
// @ts-expect-error `sockets` is readonly in `@types/node`
delete this.sockets[name];
}
}
}
// In order to properly update the socket pool, we need to call `getName()` on
// the core `https.Agent` if it is a secureEndpoint.
getName(options) {
const secureEndpoint = typeof options.secureEndpoint === 'boolean'
? options.secureEndpoint
: this.isSecureEndpoint(options);
if (secureEndpoint) {
// @ts-expect-error `getName()` isn't defined in `@types/node`
return https_1.Agent.prototype.getName.call(this, options);
}
// @ts-expect-error `getName()` isn't defined in `@types/node`
return super.getName(options);
}
createSocket(req, options, cb) {
const connectOpts = {
...options,
secureEndpoint: this.isSecureEndpoint(options),
};
const name = this.getName(connectOpts);
const fakeSocket = this.incrementSockets(name);
Promise.resolve()
.then(() => this.connect(req, connectOpts))
.then((socket) => {
this.decrementSockets(name, fakeSocket);
if (socket instanceof http.Agent) {
try {
// @ts-expect-error `addRequest()` isn't defined in `@types/node`
return socket.addRequest(req, connectOpts);
}
catch (err) {
return cb(err);
}
}
this[INTERNAL].currentSocket = socket;
// @ts-expect-error `createSocket()` isn't defined in `@types/node`
super.createSocket(req, options, cb);
}, (err) => {
this.decrementSockets(name, fakeSocket);
cb(err);
});
}
createConnection() {
const socket = this[INTERNAL].currentSocket;
this[INTERNAL].currentSocket = undefined;
if (!socket) {
throw new Error('No socket was returned in the `connect()` function');
}
return socket;
}
get defaultPort() {
return (this[INTERNAL].defaultPort ??
(this.protocol === 'https:' ? 443 : 80));
}
set defaultPort(v) {
if (this[INTERNAL]) {
this[INTERNAL].defaultPort = v;
}
}
get protocol() {
return (this[INTERNAL].protocol ??
(this.isSecureEndpoint() ? 'https:' : 'http:'));
}
set protocol(v) {
if (this[INTERNAL]) {
this[INTERNAL].protocol = v;
}
}
}
exports.Agent = Agent;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,46 @@
{
"name": "agent-base",
"version": "7.1.3",
"description": "Turn a function into an `http.Agent` instance",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "https://github.com/TooTallNate/proxy-agents.git",
"directory": "packages/agent-base"
},
"keywords": [
"http",
"agent",
"base",
"barebones",
"https"
],
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
"license": "MIT",
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/jest": "^29.5.1",
"@types/node": "^14.18.45",
"@types/semver": "^7.3.13",
"@types/ws": "^6.0.4",
"async-listen": "^3.0.0",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4",
"ws": "^5.2.4",
"tsconfig": "0.0.0"
},
"engines": {
"node": ">= 14"
},
"scripts": {
"build": "tsc",
"test": "jest --env node --verbose --bail",
"lint": "eslint . --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
}

View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,44 @@
http-proxy-agent
================
### An HTTP(s) proxy `http.Agent` implementation for HTTP
This module provides an `http.Agent` implementation that connects to a specified
HTTP or HTTPS proxy server, and can be used with the built-in `http` module.
__Note:__ For HTTP proxy usage with the `https` module, check out
[`https-proxy-agent`](../https-proxy-agent).
Example
-------
```ts
import * as http from 'http';
import { HttpProxyAgent } from 'http-proxy-agent';
const agent = new HttpProxyAgent('http://168.63.76.32:3128');
http.get('http://nodejs.org/api/', { agent }, (res) => {
console.log('"response" event!', res.headers);
res.pipe(process.stdout);
});
```
API
---
### new HttpProxyAgent(proxy: string | URL, options?: HttpProxyAgentOptions)
The `HttpProxyAgent` class implements an `http.Agent` subclass that connects
to the specified "HTTP(s) proxy server" in order to proxy HTTP requests.
The `proxy` argument is the URL for the proxy server.
The `options` argument accepts the usual `http.Agent` constructor options, and
some additional properties:
* `headers` - Object containing additional headers to send to the proxy server
in each request. This may also be a function that returns a headers object.
**NOTE:** If your proxy does not strip these headers from the request, they
will also be sent to the destination server.

View File

@@ -0,0 +1,44 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import * as net from 'net';
import * as tls from 'tls';
import * as http from 'http';
import { Agent, AgentConnectOpts } from 'agent-base';
import { URL } from 'url';
import type { OutgoingHttpHeaders } from 'http';
type Protocol<T> = T extends `${infer Protocol}:${infer _}` ? Protocol : never;
type ConnectOptsMap = {
http: Omit<net.TcpNetConnectOpts, 'host' | 'port'>;
https: Omit<tls.ConnectionOptions, 'host' | 'port'>;
};
type ConnectOpts<T> = {
[P in keyof ConnectOptsMap]: Protocol<T> extends P ? ConnectOptsMap[P] : never;
}[keyof ConnectOptsMap];
export type HttpProxyAgentOptions<T> = ConnectOpts<T> & http.AgentOptions & {
headers?: OutgoingHttpHeaders | (() => OutgoingHttpHeaders);
};
interface HttpProxyAgentClientRequest extends http.ClientRequest {
outputData?: {
data: string;
}[];
_header?: string | null;
_implicitHeader(): void;
}
/**
* The `HttpProxyAgent` implements an HTTP Agent subclass that connects
* to the specified "HTTP proxy server" in order to proxy HTTP requests.
*/
export declare class HttpProxyAgent<Uri extends string> extends Agent {
static protocols: readonly ["http", "https"];
readonly proxy: URL;
proxyHeaders: OutgoingHttpHeaders | (() => OutgoingHttpHeaders);
connectOpts: net.TcpNetConnectOpts & tls.ConnectionOptions;
constructor(proxy: Uri | URL, opts?: HttpProxyAgentOptions<Uri>);
addRequest(req: HttpProxyAgentClientRequest, opts: AgentConnectOpts): void;
setRequestProps(req: HttpProxyAgentClientRequest, opts: AgentConnectOpts): void;
connect(req: HttpProxyAgentClientRequest, opts: AgentConnectOpts): Promise<net.Socket>;
}
export {};
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAKhD,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,MAAM,QAAQ,IAAI,MAAM,CAAC,EAAE,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE/E,KAAK,cAAc,GAAG;IACrB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACnD,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CACpD,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI;KACpB,CAAC,IAAI,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,GAC/C,cAAc,CAAC,CAAC,CAAC,GACjB,KAAK;CACR,CAAC,MAAM,cAAc,CAAC,CAAC;AAExB,MAAM,MAAM,qBAAqB,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,GACpD,IAAI,CAAC,YAAY,GAAG;IACnB,OAAO,CAAC,EAAE,mBAAmB,GAAG,CAAC,MAAM,mBAAmB,CAAC,CAAC;CAC5D,CAAC;AAEH,UAAU,2BAA4B,SAAQ,IAAI,CAAC,aAAa;IAC/D,UAAU,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;KACb,EAAE,CAAC;IACJ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,eAAe,IAAI,IAAI,CAAC;CACxB;AAED;;;GAGG;AACH,qBAAa,cAAc,CAAC,GAAG,SAAS,MAAM,CAAE,SAAQ,KAAK;IAC5D,MAAM,CAAC,SAAS,6BAA8B;IAE9C,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;IACpB,YAAY,EAAE,mBAAmB,GAAG,CAAC,MAAM,mBAAmB,CAAC,CAAC;IAChE,WAAW,EAAE,GAAG,CAAC,iBAAiB,GAAG,GAAG,CAAC,iBAAiB,CAAC;gBAE/C,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,qBAAqB,CAAC,GAAG,CAAC;IAuB/D,UAAU,CAAC,GAAG,EAAE,2BAA2B,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI;IAO1E,eAAe,CACd,GAAG,EAAE,2BAA2B,EAChC,IAAI,EAAE,gBAAgB,GACpB,IAAI;IA0CD,OAAO,CACZ,GAAG,EAAE,2BAA2B,EAChC,IAAI,EAAE,gBAAgB,GACpB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;CA2CtB"}

View File

@@ -0,0 +1,148 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpProxyAgent = void 0;
const net = __importStar(require("net"));
const tls = __importStar(require("tls"));
const debug_1 = __importDefault(require("debug"));
const events_1 = require("events");
const agent_base_1 = require("agent-base");
const url_1 = require("url");
const debug = (0, debug_1.default)('http-proxy-agent');
/**
* The `HttpProxyAgent` implements an HTTP Agent subclass that connects
* to the specified "HTTP proxy server" in order to proxy HTTP requests.
*/
class HttpProxyAgent extends agent_base_1.Agent {
constructor(proxy, opts) {
super(opts);
this.proxy = typeof proxy === 'string' ? new url_1.URL(proxy) : proxy;
this.proxyHeaders = opts?.headers ?? {};
debug('Creating new HttpProxyAgent instance: %o', this.proxy.href);
// Trim off the brackets from IPv6 addresses
const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, '');
const port = this.proxy.port
? parseInt(this.proxy.port, 10)
: this.proxy.protocol === 'https:'
? 443
: 80;
this.connectOpts = {
...(opts ? omit(opts, 'headers') : null),
host,
port,
};
}
addRequest(req, opts) {
req._header = null;
this.setRequestProps(req, opts);
// @ts-expect-error `addRequest()` isn't defined in `@types/node`
super.addRequest(req, opts);
}
setRequestProps(req, opts) {
const { proxy } = this;
const protocol = opts.secureEndpoint ? 'https:' : 'http:';
const hostname = req.getHeader('host') || 'localhost';
const base = `${protocol}//${hostname}`;
const url = new url_1.URL(req.path, base);
if (opts.port !== 80) {
url.port = String(opts.port);
}
// Change the `http.ClientRequest` instance's "path" field
// to the absolute path of the URL that will be requested.
req.path = String(url);
// Inject the `Proxy-Authorization` header if necessary.
const headers = typeof this.proxyHeaders === 'function'
? this.proxyHeaders()
: { ...this.proxyHeaders };
if (proxy.username || proxy.password) {
const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`;
headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`;
}
if (!headers['Proxy-Connection']) {
headers['Proxy-Connection'] = this.keepAlive
? 'Keep-Alive'
: 'close';
}
for (const name of Object.keys(headers)) {
const value = headers[name];
if (value) {
req.setHeader(name, value);
}
}
}
async connect(req, opts) {
req._header = null;
if (!req.path.includes('://')) {
this.setRequestProps(req, opts);
}
// At this point, the http ClientRequest's internal `_header` field
// might have already been set. If this is the case then we'll need
// to re-generate the string since we just changed the `req.path`.
let first;
let endOfHeaders;
debug('Regenerating stored HTTP header string for request');
req._implicitHeader();
if (req.outputData && req.outputData.length > 0) {
debug('Patching connection write() output buffer with updated header');
first = req.outputData[0].data;
endOfHeaders = first.indexOf('\r\n\r\n') + 4;
req.outputData[0].data =
req._header + first.substring(endOfHeaders);
debug('Output buffer: %o', req.outputData[0].data);
}
// Create a socket connection to the proxy server.
let socket;
if (this.proxy.protocol === 'https:') {
debug('Creating `tls.Socket`: %o', this.connectOpts);
socket = tls.connect(this.connectOpts);
}
else {
debug('Creating `net.Socket`: %o', this.connectOpts);
socket = net.connect(this.connectOpts);
}
// Wait for the socket's `connect` event, so that this `callback()`
// function throws instead of the `http` request machinery. This is
// important for i.e. `PacProxyAgent` which determines a failed proxy
// connection via the `callback()` function throwing.
await (0, events_1.once)(socket, 'connect');
return socket;
}
}
HttpProxyAgent.protocols = ['http', 'https'];
exports.HttpProxyAgent = HttpProxyAgent;
function omit(obj, ...keys) {
const ret = {};
let key;
for (key in obj) {
if (!keys.includes(key)) {
ret[key] = obj[key];
}
}
return ret;
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,47 @@
{
"name": "http-proxy-agent",
"version": "7.0.2",
"description": "An HTTP(s) proxy `http.Agent` implementation for HTTP",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "https://github.com/TooTallNate/proxy-agents.git",
"directory": "packages/http-proxy-agent"
},
"keywords": [
"http",
"proxy",
"endpoint",
"agent"
],
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.0",
"debug": "^4.3.4"
},
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/jest": "^29.5.1",
"@types/node": "^14.18.45",
"async-listen": "^3.0.0",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4",
"proxy": "2.1.1",
"tsconfig": "0.0.0"
},
"engines": {
"node": ">= 14"
},
"scripts": {
"build": "tsc",
"test": "jest --env node --verbose --bail",
"lint": "eslint . --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
}

View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,70 @@
https-proxy-agent
================
### An HTTP(s) proxy `http.Agent` implementation for HTTPS
This module provides an `http.Agent` implementation that connects to a specified
HTTP or HTTPS proxy server, and can be used with the built-in `https` module.
Specifically, this `Agent` implementation connects to an intermediary "proxy"
server and issues the [CONNECT HTTP method][CONNECT], which tells the proxy to
open a direct TCP connection to the destination server.
Since this agent implements the CONNECT HTTP method, it also works with other
protocols that use this method when connecting over proxies (i.e. WebSockets).
See the "Examples" section below for more.
Examples
--------
#### `https` module example
```ts
import * as https from 'https';
import { HttpsProxyAgent } from 'https-proxy-agent';
const agent = new HttpsProxyAgent('http://168.63.76.32:3128');
https.get('https://example.com', { agent }, (res) => {
console.log('"response" event!', res.headers);
res.pipe(process.stdout);
});
```
#### `ws` WebSocket connection example
```ts
import WebSocket from 'ws';
import { HttpsProxyAgent } from 'https-proxy-agent';
const agent = new HttpsProxyAgent('http://168.63.76.32:3128');
const socket = new WebSocket('ws://echo.websocket.org', { agent });
socket.on('open', function () {
console.log('"open" event!');
socket.send('hello world');
});
socket.on('message', function (data, flags) {
console.log('"message" event! %j %j', data, flags);
socket.close();
});
```
API
---
### new HttpsProxyAgent(proxy: string | URL, options?: HttpsProxyAgentOptions)
The `HttpsProxyAgent` class implements an `http.Agent` subclass that connects
to the specified "HTTP(s) proxy server" in order to proxy HTTPS and/or WebSocket
requests. This is achieved by using the [HTTP `CONNECT` method][CONNECT].
The `proxy` argument is the URL for the proxy server.
The `options` argument accepts the usual `http.Agent` constructor options, and
some additional properties:
* `headers` - Object containing additional headers to send to the proxy server
in the `CONNECT` request.
[CONNECT]: http://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_Tunneling

View File

@@ -0,0 +1,47 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import * as net from 'net';
import * as tls from 'tls';
import * as http from 'http';
import { Agent, AgentConnectOpts } from 'agent-base';
import { URL } from 'url';
import type { OutgoingHttpHeaders } from 'http';
type Protocol<T> = T extends `${infer Protocol}:${infer _}` ? Protocol : never;
type ConnectOptsMap = {
http: Omit<net.TcpNetConnectOpts, 'host' | 'port'>;
https: Omit<tls.ConnectionOptions, 'host' | 'port'>;
};
type ConnectOpts<T> = {
[P in keyof ConnectOptsMap]: Protocol<T> extends P ? ConnectOptsMap[P] : never;
}[keyof ConnectOptsMap];
export type HttpsProxyAgentOptions<T> = ConnectOpts<T> & http.AgentOptions & {
headers?: OutgoingHttpHeaders | (() => OutgoingHttpHeaders);
};
/**
* The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to
* the specified "HTTP(s) proxy server" in order to proxy HTTPS requests.
*
* Outgoing HTTP requests are first tunneled through the proxy server using the
* `CONNECT` HTTP request method to establish a connection to the proxy server,
* and then the proxy server connects to the destination target and issues the
* HTTP request from the proxy server.
*
* `https:` requests have their socket connection upgraded to TLS once
* the connection to the proxy server has been established.
*/
export declare class HttpsProxyAgent<Uri extends string> extends Agent {
static protocols: readonly ["http", "https"];
readonly proxy: URL;
proxyHeaders: OutgoingHttpHeaders | (() => OutgoingHttpHeaders);
connectOpts: net.TcpNetConnectOpts & tls.ConnectionOptions;
constructor(proxy: Uri | URL, opts?: HttpsProxyAgentOptions<Uri>);
/**
* Called when the node-core HTTP client library is creating a
* new HTTP request.
*/
connect(req: http.ClientRequest, opts: AgentConnectOpts): Promise<net.Socket>;
}
export {};
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAuBhD,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,MAAM,QAAQ,IAAI,MAAM,CAAC,EAAE,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE/E,KAAK,cAAc,GAAG;IACrB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACnD,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;CACpD,CAAC;AAEF,KAAK,WAAW,CAAC,CAAC,IAAI;KACpB,CAAC,IAAI,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,GAC/C,cAAc,CAAC,CAAC,CAAC,GACjB,KAAK;CACR,CAAC,MAAM,cAAc,CAAC,CAAC;AAExB,MAAM,MAAM,sBAAsB,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,GACrD,IAAI,CAAC,YAAY,GAAG;IACnB,OAAO,CAAC,EAAE,mBAAmB,GAAG,CAAC,MAAM,mBAAmB,CAAC,CAAC;CAC5D,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,qBAAa,eAAe,CAAC,GAAG,SAAS,MAAM,CAAE,SAAQ,KAAK;IAC7D,MAAM,CAAC,SAAS,6BAA8B;IAE9C,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC;IACpB,YAAY,EAAE,mBAAmB,GAAG,CAAC,MAAM,mBAAmB,CAAC,CAAC;IAChE,WAAW,EAAE,GAAG,CAAC,iBAAiB,GAAG,GAAG,CAAC,iBAAiB,CAAC;gBAE/C,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,sBAAsB,CAAC,GAAG,CAAC;IA0BhE;;;OAGG;IACG,OAAO,CACZ,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,IAAI,EAAE,gBAAgB,GACpB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;CAwGtB"}

View File

@@ -0,0 +1,180 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpsProxyAgent = void 0;
const net = __importStar(require("net"));
const tls = __importStar(require("tls"));
const assert_1 = __importDefault(require("assert"));
const debug_1 = __importDefault(require("debug"));
const agent_base_1 = require("agent-base");
const url_1 = require("url");
const parse_proxy_response_1 = require("./parse-proxy-response");
const debug = (0, debug_1.default)('https-proxy-agent');
const setServernameFromNonIpHost = (options) => {
if (options.servername === undefined &&
options.host &&
!net.isIP(options.host)) {
return {
...options,
servername: options.host,
};
}
return options;
};
/**
* The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to
* the specified "HTTP(s) proxy server" in order to proxy HTTPS requests.
*
* Outgoing HTTP requests are first tunneled through the proxy server using the
* `CONNECT` HTTP request method to establish a connection to the proxy server,
* and then the proxy server connects to the destination target and issues the
* HTTP request from the proxy server.
*
* `https:` requests have their socket connection upgraded to TLS once
* the connection to the proxy server has been established.
*/
class HttpsProxyAgent extends agent_base_1.Agent {
constructor(proxy, opts) {
super(opts);
this.options = { path: undefined };
this.proxy = typeof proxy === 'string' ? new url_1.URL(proxy) : proxy;
this.proxyHeaders = opts?.headers ?? {};
debug('Creating new HttpsProxyAgent instance: %o', this.proxy.href);
// Trim off the brackets from IPv6 addresses
const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, '');
const port = this.proxy.port
? parseInt(this.proxy.port, 10)
: this.proxy.protocol === 'https:'
? 443
: 80;
this.connectOpts = {
// Attempt to negotiate http/1.1 for proxy servers that support http/2
ALPNProtocols: ['http/1.1'],
...(opts ? omit(opts, 'headers') : null),
host,
port,
};
}
/**
* Called when the node-core HTTP client library is creating a
* new HTTP request.
*/
async connect(req, opts) {
const { proxy } = this;
if (!opts.host) {
throw new TypeError('No "host" provided');
}
// Create a socket connection to the proxy server.
let socket;
if (proxy.protocol === 'https:') {
debug('Creating `tls.Socket`: %o', this.connectOpts);
socket = tls.connect(setServernameFromNonIpHost(this.connectOpts));
}
else {
debug('Creating `net.Socket`: %o', this.connectOpts);
socket = net.connect(this.connectOpts);
}
const headers = typeof this.proxyHeaders === 'function'
? this.proxyHeaders()
: { ...this.proxyHeaders };
const host = net.isIPv6(opts.host) ? `[${opts.host}]` : opts.host;
let payload = `CONNECT ${host}:${opts.port} HTTP/1.1\r\n`;
// Inject the `Proxy-Authorization` header if necessary.
if (proxy.username || proxy.password) {
const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`;
headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`;
}
headers.Host = `${host}:${opts.port}`;
if (!headers['Proxy-Connection']) {
headers['Proxy-Connection'] = this.keepAlive
? 'Keep-Alive'
: 'close';
}
for (const name of Object.keys(headers)) {
payload += `${name}: ${headers[name]}\r\n`;
}
const proxyResponsePromise = (0, parse_proxy_response_1.parseProxyResponse)(socket);
socket.write(`${payload}\r\n`);
const { connect, buffered } = await proxyResponsePromise;
req.emit('proxyConnect', connect);
this.emit('proxyConnect', connect, req);
if (connect.statusCode === 200) {
req.once('socket', resume);
if (opts.secureEndpoint) {
// The proxy is connecting to a TLS server, so upgrade
// this socket connection to a TLS connection.
debug('Upgrading socket connection to TLS');
return tls.connect({
...omit(setServernameFromNonIpHost(opts), 'host', 'path', 'port'),
socket,
});
}
return socket;
}
// Some other status code that's not 200... need to re-play the HTTP
// header "data" events onto the socket once the HTTP machinery is
// attached so that the node core `http` can parse and handle the
// error status code.
// Close the original socket, and a new "fake" socket is returned
// instead, so that the proxy doesn't get the HTTP request
// written to it (which may contain `Authorization` headers or other
// sensitive data).
//
// See: https://hackerone.com/reports/541502
socket.destroy();
const fakeSocket = new net.Socket({ writable: false });
fakeSocket.readable = true;
// Need to wait for the "socket" event to re-play the "data" events.
req.once('socket', (s) => {
debug('Replaying proxy buffer for failed request');
(0, assert_1.default)(s.listenerCount('data') > 0);
// Replay the "buffered" Buffer onto the fake `socket`, since at
// this point the HTTP module machinery has been hooked up for
// the user.
s.push(buffered);
s.push(null);
});
return fakeSocket;
}
}
HttpsProxyAgent.protocols = ['http', 'https'];
exports.HttpsProxyAgent = HttpsProxyAgent;
function resume(socket) {
socket.resume();
}
function omit(obj, ...keys) {
const ret = {};
let key;
for (key in obj) {
if (!keys.includes(key)) {
ret[key] = obj[key];
}
}
return ret;
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,15 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import { IncomingHttpHeaders } from 'http';
import { Readable } from 'stream';
export interface ConnectResponse {
statusCode: number;
statusText: string;
headers: IncomingHttpHeaders;
}
export declare function parseProxyResponse(socket: Readable): Promise<{
connect: ConnectResponse;
buffered: Buffer;
}>;
//# sourceMappingURL=parse-proxy-response.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parse-proxy-response.d.ts","sourceRoot":"","sources":["../src/parse-proxy-response.ts"],"names":[],"mappings":";;;AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIlC,MAAM,WAAW,eAAe;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,mBAAmB,CAAC;CAC7B;AAED,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,QAAQ,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAyGzD"}

View File

@@ -0,0 +1,101 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseProxyResponse = void 0;
const debug_1 = __importDefault(require("debug"));
const debug = (0, debug_1.default)('https-proxy-agent:parse-proxy-response');
function parseProxyResponse(socket) {
return new Promise((resolve, reject) => {
// we need to buffer any HTTP traffic that happens with the proxy before we get
// the CONNECT response, so that if the response is anything other than an "200"
// response code, then we can re-play the "data" events on the socket once the
// HTTP parser is hooked up...
let buffersLength = 0;
const buffers = [];
function read() {
const b = socket.read();
if (b)
ondata(b);
else
socket.once('readable', read);
}
function cleanup() {
socket.removeListener('end', onend);
socket.removeListener('error', onerror);
socket.removeListener('readable', read);
}
function onend() {
cleanup();
debug('onend');
reject(new Error('Proxy connection ended before receiving CONNECT response'));
}
function onerror(err) {
cleanup();
debug('onerror %o', err);
reject(err);
}
function ondata(b) {
buffers.push(b);
buffersLength += b.length;
const buffered = Buffer.concat(buffers, buffersLength);
const endOfHeaders = buffered.indexOf('\r\n\r\n');
if (endOfHeaders === -1) {
// keep buffering
debug('have not received end of HTTP headers yet...');
read();
return;
}
const headerParts = buffered
.slice(0, endOfHeaders)
.toString('ascii')
.split('\r\n');
const firstLine = headerParts.shift();
if (!firstLine) {
socket.destroy();
return reject(new Error('No header received from proxy CONNECT response'));
}
const firstLineParts = firstLine.split(' ');
const statusCode = +firstLineParts[1];
const statusText = firstLineParts.slice(2).join(' ');
const headers = {};
for (const header of headerParts) {
if (!header)
continue;
const firstColon = header.indexOf(':');
if (firstColon === -1) {
socket.destroy();
return reject(new Error(`Invalid header from proxy CONNECT response: "${header}"`));
}
const key = header.slice(0, firstColon).toLowerCase();
const value = header.slice(firstColon + 1).trimStart();
const current = headers[key];
if (typeof current === 'string') {
headers[key] = [current, value];
}
else if (Array.isArray(current)) {
current.push(value);
}
else {
headers[key] = value;
}
}
debug('got proxy server response: %o %o', firstLine, headers);
cleanup();
resolve({
connect: {
statusCode,
statusText,
headers,
},
buffered,
});
}
socket.on('error', onerror);
socket.on('end', onend);
read();
});
}
exports.parseProxyResponse = parseProxyResponse;
//# sourceMappingURL=parse-proxy-response.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parse-proxy-response.js","sourceRoot":"","sources":["../src/parse-proxy-response.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,50 @@
{
"name": "https-proxy-agent",
"version": "7.0.6",
"description": "An HTTP(s) proxy `http.Agent` implementation for HTTPS",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "https://github.com/TooTallNate/proxy-agents.git",
"directory": "packages/https-proxy-agent"
},
"keywords": [
"https",
"proxy",
"endpoint",
"agent"
],
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
},
"devDependencies": {
"@types/async-retry": "^1.4.5",
"@types/debug": "4",
"@types/jest": "^29.5.1",
"@types/node": "^14.18.45",
"async-listen": "^3.0.0",
"async-retry": "^1.3.3",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4",
"proxy": "2.2.0",
"tsconfig": "0.0.0"
},
"engines": {
"node": ">= 14"
},
"scripts": {
"build": "tsc",
"test": "jest --env node --verbose --bail test/test.ts",
"test-e2e": "jest --env node --verbose --bail test/e2e.test.ts",
"lint": "eslint --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
}

View File

@@ -0,0 +1,15 @@
The ISC License
Copyright (c) 2010-2023 Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,869 @@
// Project: https://github.com/isaacs/node-lru-cache
// Based initially on @types/lru-cache
// https://github.com/DefinitelyTyped/DefinitelyTyped
// used under the terms of the MIT License, shown below.
//
// DefinitelyTyped license:
// ------
// MIT License
//
// Copyright (c) Microsoft Corporation.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
// ------
//
// Changes by Isaac Z. Schlueter released under the terms found in the
// LICENSE file within this project.
/**
* Integer greater than 0, representing some number of milliseconds, or the
* time at which a TTL started counting from.
*/
declare type LRUMilliseconds = number
/**
* An integer greater than 0, reflecting the calculated size of items
*/
declare type LRUSize = number
/**
* An integer greater than 0, reflecting a number of items
*/
declare type LRUCount = number
declare class LRUCache<K, V> implements Iterable<[K, V]> {
constructor(options: LRUCache.Options<K, V>)
/**
* Number of items in the cache.
* Alias for {@link size}
*
* @deprecated since 7.0 use {@link size} instead
*/
public readonly length: LRUCount
public readonly max: LRUCount
public readonly maxSize: LRUSize
public readonly maxEntrySize: LRUSize
public readonly sizeCalculation:
| LRUCache.SizeCalculator<K, V>
| undefined
public readonly dispose: LRUCache.Disposer<K, V>
/**
* @since 7.4.0
*/
public readonly disposeAfter: LRUCache.Disposer<K, V> | null
public readonly noDisposeOnSet: boolean
public readonly ttl: LRUMilliseconds
public readonly ttlResolution: LRUMilliseconds
public readonly ttlAutopurge: boolean
public readonly allowStale: boolean
public readonly updateAgeOnGet: boolean
/**
* @since 7.11.0
*/
public readonly noDeleteOnStaleGet: boolean
/**
* @since 7.6.0
*/
public readonly fetchMethod: LRUCache.Fetcher<K, V> | null
/**
* The total number of items held in the cache at the current moment.
*/
public readonly size: LRUCount
/**
* The total size of items in cache when using size tracking.
*/
public readonly calculatedSize: LRUSize
/**
* Add a value to the cache.
*/
public set(
key: K,
value: V,
options?: LRUCache.SetOptions<K, V>
): this
/**
* Return a value from the cache. Will update the recency of the cache entry
* found.
*
* If the key is not found, {@link get} will return `undefined`. This can be
* confusing when setting values specifically to `undefined`, as in
* `cache.set(key, undefined)`. Use {@link has} to determine whether a key is
* present in the cache at all.
*/
public get(key: K, options?: LRUCache.GetOptions<V>): V | undefined
/**
* Like {@link get} but doesn't update recency or delete stale items.
* Returns `undefined` if the item is stale, unless {@link allowStale} is set
* either on the cache or in the options object.
*/
public peek(key: K, options?: LRUCache.PeekOptions): V | undefined
/**
* Check if a key is in the cache, without updating the recency of use.
* Will return false if the item is stale, even though it is technically
* in the cache.
*
* Will not update item age unless {@link updateAgeOnHas} is set in the
* options or constructor.
*/
public has(key: K, options?: LRUCache.HasOptions<V>): boolean
/**
* Deletes a key out of the cache.
* Returns true if the key was deleted, false otherwise.
*/
public delete(key: K): boolean
/**
* Clear the cache entirely, throwing away all values.
*/
public clear(): void
/**
* Delete any stale entries. Returns true if anything was removed, false
* otherwise.
*/
public purgeStale(): boolean
/**
* Find a value for which the supplied fn method returns a truthy value,
* similar to Array.find(). fn is called as fn(value, key, cache).
*/
public find(
callbackFn: (
value: V,
key: K,
cache: this
) => boolean | undefined | void,
options?: LRUCache.GetOptions<V>
): V | undefined
/**
* Call the supplied function on each item in the cache, in order from
* most recently used to least recently used. fn is called as
* fn(value, key, cache). Does not update age or recenty of use.
*/
public forEach<T = this>(
callbackFn: (this: T, value: V, key: K, cache: this) => void,
thisArg?: T
): void
/**
* The same as {@link forEach} but items are iterated over in reverse
* order. (ie, less recently used items are iterated over first.)
*/
public rforEach<T = this>(
callbackFn: (this: T, value: V, key: K, cache: this) => void,
thisArg?: T
): void
/**
* Return a generator yielding the keys in the cache,
* in order from most recently used to least recently used.
*/
public keys(): Generator<K, void, void>
/**
* Inverse order version of {@link keys}
*
* Return a generator yielding the keys in the cache,
* in order from least recently used to most recently used.
*/
public rkeys(): Generator<K, void, void>
/**
* Return a generator yielding the values in the cache,
* in order from most recently used to least recently used.
*/
public values(): Generator<V, void, void>
/**
* Inverse order version of {@link values}
*
* Return a generator yielding the values in the cache,
* in order from least recently used to most recently used.
*/
public rvalues(): Generator<V, void, void>
/**
* Return a generator yielding `[key, value]` pairs,
* in order from most recently used to least recently used.
*/
public entries(): Generator<[K, V], void, void>
/**
* Inverse order version of {@link entries}
*
* Return a generator yielding `[key, value]` pairs,
* in order from least recently used to most recently used.
*/
public rentries(): Generator<[K, V], void, void>
/**
* Iterating over the cache itself yields the same results as
* {@link entries}
*/
public [Symbol.iterator](): Generator<[K, V], void, void>
/**
* Return an array of [key, entry] objects which can be passed to
* cache.load()
*/
public dump(): Array<[K, LRUCache.Entry<V>]>
/**
* Reset the cache and load in the items in entries in the order listed.
* Note that the shape of the resulting cache may be different if the
* same options are not used in both caches.
*/
public load(
cacheEntries: ReadonlyArray<[K, LRUCache.Entry<V>]>
): void
/**
* Evict the least recently used item, returning its value or `undefined`
* if cache is empty.
*/
public pop(): V | undefined
/**
* Deletes a key out of the cache.
*
* @deprecated since 7.0 use delete() instead
*/
public del(key: K): boolean
/**
* Clear the cache entirely, throwing away all values.
*
* @deprecated since 7.0 use clear() instead
*/
public reset(): void
/**
* Manually iterates over the entire cache proactively pruning old entries.
*
* @deprecated since 7.0 use purgeStale() instead
*/
public prune(): boolean
/**
* Make an asynchronous cached fetch using the {@link fetchMethod} function.
*
* If multiple fetches for the same key are issued, then they will all be
* coalesced into a single call to fetchMethod.
*
* Note that this means that handling options such as
* {@link allowStaleOnFetchAbort}, {@link signal}, and
* {@link allowStaleOnFetchRejection} will be determined by the FIRST fetch()
* call for a given key.
*
* This is a known (fixable) shortcoming which will be addresed on when
* someone complains about it, as the fix would involve added complexity and
* may not be worth the costs for this edge case.
*
* since: 7.6.0
*/
public fetch(
key: K,
options?: LRUCache.FetchOptions<K, V>
): Promise<V>
/**
* since: 7.6.0
*/
public getRemainingTTL(key: K): LRUMilliseconds
}
declare namespace LRUCache {
type DisposeReason = 'evict' | 'set' | 'delete'
type SizeCalculator<K, V> = (value: V, key: K) => LRUSize
type Disposer<K, V> = (
value: V,
key: K,
reason: DisposeReason
) => void
type Fetcher<K, V> = (
key: K,
staleValue: V | undefined,
options: FetcherOptions<K, V>
) => Promise<V | void | undefined> | V | void | undefined
interface DeprecatedOptions<K, V> {
/**
* alias for ttl
*
* @deprecated since 7.0 use options.ttl instead
*/
maxAge?: LRUMilliseconds
/**
* alias for {@link sizeCalculation}
*
* @deprecated since 7.0 use {@link sizeCalculation} instead
*/
length?: SizeCalculator<K, V>
/**
* alias for allowStale
*
* @deprecated since 7.0 use options.allowStale instead
*/
stale?: boolean
}
interface LimitedByCount {
/**
* The number of most recently used items to keep.
* Note that we may store fewer items than this if maxSize is hit.
*/
max: LRUCount
}
type MaybeMaxEntrySizeLimit<K, V> =
| {
/**
* The maximum allowed size for any single item in the cache.
*
* If a larger item is passed to {@link set} or returned by a
* {@link fetchMethod}, then it will not be stored in the cache.
*/
maxEntrySize: LRUSize
sizeCalculation?: SizeCalculator<K, V>
}
| {}
interface LimitedBySize<K, V> {
/**
* If you wish to track item size, you must provide a maxSize
* note that we still will only keep up to max *actual items*,
* if max is set, so size tracking may cause fewer than max items
* to be stored. At the extreme, a single item of maxSize size
* will cause everything else in the cache to be dropped when it
* is added. Use with caution!
*
* Note also that size tracking can negatively impact performance,
* though for most cases, only minimally.
*/
maxSize: LRUSize
/**
* Function to calculate size of items. Useful if storing strings or
* buffers or other items where memory size depends on the object itself.
*
* Items larger than {@link maxEntrySize} will not be stored in the cache.
*
* Note that when {@link maxSize} or {@link maxEntrySize} are set, every
* item added MUST have a size specified, either via a `sizeCalculation` in
* the constructor, or `sizeCalculation` or {@link size} options to
* {@link set}.
*/
sizeCalculation?: SizeCalculator<K, V>
}
interface LimitedByTTL {
/**
* Max time in milliseconds for items to live in cache before they are
* considered stale. Note that stale items are NOT preemptively removed
* by default, and MAY live in the cache, contributing to its LRU max,
* long after they have expired.
*
* Also, as this cache is optimized for LRU/MRU operations, some of
* the staleness/TTL checks will reduce performance, as they will incur
* overhead by deleting items.
*
* Must be an integer number of ms, defaults to 0, which means "no TTL"
*/
ttl: LRUMilliseconds
/**
* Boolean flag to tell the cache to not update the TTL when
* setting a new value for an existing key (ie, when updating a value
* rather than inserting a new value). Note that the TTL value is
* _always_ set (if provided) when adding a new entry into the cache.
*
* @default false
* @since 7.4.0
*/
noUpdateTTL?: boolean
/**
* Minimum amount of time in ms in which to check for staleness.
* Defaults to 1, which means that the current time is checked
* at most once per millisecond.
*
* Set to 0 to check the current time every time staleness is tested.
* (This reduces performance, and is theoretically unnecessary.)
*
* Setting this to a higher value will improve performance somewhat
* while using ttl tracking, albeit at the expense of keeping stale
* items around a bit longer than their TTLs would indicate.
*
* @default 1
* @since 7.1.0
*/
ttlResolution?: LRUMilliseconds
/**
* Preemptively remove stale items from the cache.
* Note that this may significantly degrade performance,
* especially if the cache is storing a large number of items.
* It is almost always best to just leave the stale items in
* the cache, and let them fall out as new items are added.
*
* Note that this means that {@link allowStale} is a bit pointless,
* as stale items will be deleted almost as soon as they expire.
*
* Use with caution!
*
* @default false
* @since 7.1.0
*/
ttlAutopurge?: boolean
/**
* Return stale items from {@link get} before disposing of them.
* Return stale values from {@link fetch} while performing a call
* to the {@link fetchMethod} in the background.
*
* @default false
*/
allowStale?: boolean
/**
* Update the age of items on {@link get}, renewing their TTL
*
* @default false
*/
updateAgeOnGet?: boolean
/**
* Do not delete stale items when they are retrieved with {@link get}.
* Note that the {@link get} return value will still be `undefined` unless
* allowStale is true.
*
* @default false
* @since 7.11.0
*/
noDeleteOnStaleGet?: boolean
/**
* Update the age of items on {@link has}, renewing their TTL
*
* @default false
*/
updateAgeOnHas?: boolean
}
type SafetyBounds<K, V> =
| LimitedByCount
| LimitedBySize<K, V>
| LimitedByTTL
// options shared by all three of the limiting scenarios
interface SharedOptions<K, V> {
/**
* Function that is called on items when they are dropped from the cache.
* This can be handy if you want to close file descriptors or do other
* cleanup tasks when items are no longer accessible. Called with `key,
* value`. It's called before actually removing the item from the
* internal cache, so it is *NOT* safe to re-add them.
* Use {@link disposeAfter} if you wish to dispose items after they have
* been full removed, when it is safe to add them back to the cache.
*/
dispose?: Disposer<K, V>
/**
* The same as dispose, but called *after* the entry is completely
* removed and the cache is once again in a clean state. It is safe to
* add an item right back into the cache at this point.
* However, note that it is *very* easy to inadvertently create infinite
* recursion this way.
*
* @since 7.3.0
*/
disposeAfter?: Disposer<K, V>
/**
* Set to true to suppress calling the dispose() function if the entry
* key is still accessible within the cache.
* This may be overridden by passing an options object to {@link set}.
*
* @default false
*/
noDisposeOnSet?: boolean
/**
* Function that is used to make background asynchronous fetches. Called
* with `fetchMethod(key, staleValue, { signal, options, context })`.
*
* If `fetchMethod` is not provided, then {@link fetch} is
* equivalent to `Promise.resolve(cache.get(key))`.
*
* The `fetchMethod` should ONLY return `undefined` in cases where the
* abort controller has sent an abort signal.
*
* @since 7.6.0
*/
fetchMethod?: LRUCache.Fetcher<K, V>
/**
* Set to true to suppress the deletion of stale data when a
* {@link fetchMethod} throws an error or returns a rejected promise
*
* This may be overridden in the {@link fetchMethod}.
*
* @default false
* @since 7.10.0
*/
noDeleteOnFetchRejection?: boolean
/**
* Set to true to allow returning stale data when a {@link fetchMethod}
* throws an error or returns a rejected promise. Note that this
* differs from using {@link allowStale} in that stale data will
* ONLY be returned in the case that the fetch fails, not any other
* times.
*
* This may be overridden in the {@link fetchMethod}.
*
* @default false
* @since 7.16.0
*/
allowStaleOnFetchRejection?: boolean
/**
*
* Set to true to ignore the `abort` event emitted by the `AbortSignal`
* object passed to {@link fetchMethod}, and still cache the
* resulting resolution value, as long as it is not `undefined`.
*
* When used on its own, this means aborted {@link fetch} calls are not
* immediately resolved or rejected when they are aborted, and instead take
* the full time to await.
*
* When used with {@link allowStaleOnFetchAbort}, aborted {@link fetch}
* calls will resolve immediately to their stale cached value or
* `undefined`, and will continue to process and eventually update the
* cache when they resolve, as long as the resulting value is not
* `undefined`, thus supporting a "return stale on timeout while
* refreshing" mechanism by passing `AbortSignal.timeout(n)` as the signal.
*
* **Note**: regardless of this setting, an `abort` event _is still emitted
* on the `AbortSignal` object_, so may result in invalid results when
* passed to other underlying APIs that use AbortSignals.
*
* This may be overridden in the {@link fetchMethod} or the call to
* {@link fetch}.
*
* @default false
* @since 7.17.0
*/
ignoreFetchAbort?: boolean
/**
* Set to true to return a stale value from the cache when the
* `AbortSignal` passed to the {@link fetchMethod} dispatches an `'abort'`
* event, whether user-triggered, or due to internal cache behavior.
*
* Unless {@link ignoreFetchAbort} is also set, the underlying
* {@link fetchMethod} will still be considered canceled, and its return
* value will be ignored and not cached.
*
* This may be overridden in the {@link fetchMethod} or the call to
* {@link fetch}.
*
* @default false
* @since 7.17.0
*/
allowStaleOnFetchAbort?: boolean
/**
* Set to any value in the constructor or {@link fetch} options to
* pass arbitrary data to the {@link fetchMethod} in the {@link context}
* options field.
*
* @since 7.12.0
*/
fetchContext?: any
}
type Options<K, V> = SharedOptions<K, V> &
DeprecatedOptions<K, V> &
SafetyBounds<K, V> &
MaybeMaxEntrySizeLimit<K, V>
/**
* options which override the options set in the LRUCache constructor
* when making calling {@link set}.
*/
interface SetOptions<K, V> {
/**
* A value for the size of the entry, prevents calls to
* {@link sizeCalculation}.
*
* Items larger than {@link maxEntrySize} will not be stored in the cache.
*
* Note that when {@link maxSize} or {@link maxEntrySize} are set, every
* item added MUST have a size specified, either via a `sizeCalculation` in
* the constructor, or {@link sizeCalculation} or `size` options to
* {@link set}.
*/
size?: LRUSize
/**
* Overrides the {@link sizeCalculation} method set in the constructor.
*
* Items larger than {@link maxEntrySize} will not be stored in the cache.
*
* Note that when {@link maxSize} or {@link maxEntrySize} are set, every
* item added MUST have a size specified, either via a `sizeCalculation` in
* the constructor, or `sizeCalculation` or {@link size} options to
* {@link set}.
*/
sizeCalculation?: SizeCalculator<K, V>
ttl?: LRUMilliseconds
start?: LRUMilliseconds
noDisposeOnSet?: boolean
noUpdateTTL?: boolean
status?: Status<V>
}
/**
* options which override the options set in the LRUCAche constructor
* when calling {@link has}.
*/
interface HasOptions<V> {
updateAgeOnHas?: boolean
status: Status<V>
}
/**
* options which override the options set in the LRUCache constructor
* when calling {@link get}.
*/
interface GetOptions<V> {
allowStale?: boolean
updateAgeOnGet?: boolean
noDeleteOnStaleGet?: boolean
status?: Status<V>
}
/**
* options which override the options set in the LRUCache constructor
* when calling {@link peek}.
*/
interface PeekOptions {
allowStale?: boolean
}
/**
* Options object passed to the {@link fetchMethod}
*
* May be mutated by the {@link fetchMethod} to affect the behavior of the
* resulting {@link set} operation on resolution, or in the case of
* {@link noDeleteOnFetchRejection}, {@link ignoreFetchAbort}, and
* {@link allowStaleOnFetchRejection}, the handling of failure.
*/
interface FetcherFetchOptions<K, V> {
allowStale?: boolean
updateAgeOnGet?: boolean
noDeleteOnStaleGet?: boolean
size?: LRUSize
sizeCalculation?: SizeCalculator<K, V>
ttl?: LRUMilliseconds
noDisposeOnSet?: boolean
noUpdateTTL?: boolean
noDeleteOnFetchRejection?: boolean
allowStaleOnFetchRejection?: boolean
ignoreFetchAbort?: boolean
allowStaleOnFetchAbort?: boolean
status?: Status<V>
}
/**
* Status object that may be passed to {@link fetch}, {@link get},
* {@link set}, and {@link has}.
*/
interface Status<V> {
/**
* The status of a set() operation.
*
* - add: the item was not found in the cache, and was added
* - update: the item was in the cache, with the same value provided
* - replace: the item was in the cache, and replaced
* - miss: the item was not added to the cache for some reason
*/
set?: 'add' | 'update' | 'replace' | 'miss'
/**
* the ttl stored for the item, or undefined if ttls are not used.
*/
ttl?: LRUMilliseconds
/**
* the start time for the item, or undefined if ttls are not used.
*/
start?: LRUMilliseconds
/**
* The timestamp used for TTL calculation
*/
now?: LRUMilliseconds
/**
* the remaining ttl for the item, or undefined if ttls are not used.
*/
remainingTTL?: LRUMilliseconds
/**
* The calculated size for the item, if sizes are used.
*/
size?: LRUSize
/**
* A flag indicating that the item was not stored, due to exceeding the
* {@link maxEntrySize}
*/
maxEntrySizeExceeded?: true
/**
* The old value, specified in the case of `set:'update'` or
* `set:'replace'`
*/
oldValue?: V
/**
* The results of a {@link has} operation
*
* - hit: the item was found in the cache
* - stale: the item was found in the cache, but is stale
* - miss: the item was not found in the cache
*/
has?: 'hit' | 'stale' | 'miss'
/**
* The status of a {@link fetch} operation.
* Note that this can change as the underlying fetch() moves through
* various states.
*
* - inflight: there is another fetch() for this key which is in process
* - get: there is no fetchMethod, so {@link get} was called.
* - miss: the item is not in cache, and will be fetched.
* - hit: the item is in the cache, and was resolved immediately.
* - stale: the item is in the cache, but stale.
* - refresh: the item is in the cache, and not stale, but
* {@link forceRefresh} was specified.
*/
fetch?: 'get' | 'inflight' | 'miss' | 'hit' | 'stale' | 'refresh'
/**
* The {@link fetchMethod} was called
*/
fetchDispatched?: true
/**
* The cached value was updated after a successful call to fetchMethod
*/
fetchUpdated?: true
/**
* The reason for a fetch() rejection. Either the error raised by the
* {@link fetchMethod}, or the reason for an AbortSignal.
*/
fetchError?: Error
/**
* The fetch received an abort signal
*/
fetchAborted?: true
/**
* The abort signal received was ignored, and the fetch was allowed to
* continue.
*/
fetchAbortIgnored?: true
/**
* The fetchMethod promise resolved successfully
*/
fetchResolved?: true
/**
* The fetchMethod promise was rejected
*/
fetchRejected?: true
/**
* The status of a {@link get} operation.
*
* - fetching: The item is currently being fetched. If a previous value is
* present and allowed, that will be returned.
* - stale: The item is in the cache, and is stale.
* - hit: the item is in the cache
* - miss: the item is not in the cache
*/
get?: 'stale' | 'hit' | 'miss'
/**
* A fetch or get operation returned a stale value.
*/
returnedStale?: true
}
/**
* options which override the options set in the LRUCache constructor
* when calling {@link fetch}.
*
* This is the union of GetOptions and SetOptions, plus
* {@link noDeleteOnFetchRejection}, {@link allowStaleOnFetchRejection},
* {@link forceRefresh}, and {@link fetchContext}
*/
interface FetchOptions<K, V> extends FetcherFetchOptions<K, V> {
forceRefresh?: boolean
fetchContext?: any
signal?: AbortSignal
status?: Status<V>
}
interface FetcherOptions<K, V> {
signal: AbortSignal
options: FetcherFetchOptions<K, V>
/**
* Object provided in the {@link fetchContext} option
*/
context: any
}
interface Entry<V> {
value: V
ttl?: LRUMilliseconds
size?: LRUSize
start?: LRUMilliseconds
}
}
export = LRUCache

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,96 @@
{
"name": "lru-cache",
"description": "A cache object that deletes the least-recently-used items.",
"version": "7.18.3",
"author": "Isaac Z. Schlueter <i@izs.me>",
"keywords": [
"mru",
"lru",
"cache"
],
"sideEffects": false,
"scripts": {
"build": "npm run prepare",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"prepare": "node ./scripts/transpile-to-esm.js",
"size": "size-limit",
"test": "tap",
"snap": "tap",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"format": "prettier --write .",
"typedoc": "typedoc ./index.d.ts"
},
"type": "commonjs",
"main": "./index.js",
"module": "./index.mjs",
"types": "./index.d.ts",
"exports": {
".": {
"import": {
"types": "./index.d.ts",
"default": "./index.mjs"
},
"require": {
"types": "./index.d.ts",
"default": "./index.js"
}
},
"./package.json": "./package.json"
},
"repository": "git://github.com/isaacs/node-lru-cache.git",
"devDependencies": {
"@size-limit/preset-small-lib": "^7.0.8",
"@types/node": "^17.0.31",
"@types/tap": "^15.0.6",
"benchmark": "^2.1.4",
"c8": "^7.11.2",
"clock-mock": "^1.0.6",
"eslint-config-prettier": "^8.5.0",
"prettier": "^2.6.2",
"size-limit": "^7.0.8",
"tap": "^16.3.4",
"ts-node": "^10.7.0",
"tslib": "^2.4.0",
"typedoc": "^0.23.24",
"typescript": "^4.6.4"
},
"license": "ISC",
"files": [
"index.js",
"index.mjs",
"index.d.ts"
],
"engines": {
"node": ">=12"
},
"prettier": {
"semi": false,
"printWidth": 70,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"jsxSingleQuote": false,
"bracketSameLine": true,
"arrowParens": "avoid",
"endOfLine": "lf"
},
"tap": {
"nyc-arg": [
"--include=index.js"
],
"node-arg": [
"--expose-gc",
"--require",
"ts-node/register"
],
"ts": false
},
"size-limit": [
{
"path": "./index.js"
}
]
}

View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,50 @@
socks-proxy-agent
================
### A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS
This module provides an `http.Agent` implementation that connects to a
specified SOCKS proxy server, and can be used with the built-in `http`
and `https` modules.
It can also be used in conjunction with the `ws` module to establish a WebSocket
connection over a SOCKS proxy. See the "Examples" section below.
Examples
--------
```ts
import https from 'https';
import { SocksProxyAgent } from 'socks-proxy-agent';
const agent = new SocksProxyAgent(
'socks://your-name%40gmail.com:abcdef12345124@br41.nordvpn.com'
);
https.get('https://ipinfo.io', { agent }, (res) => {
console.log(res.headers);
res.pipe(process.stdout);
});
```
#### `ws` WebSocket connection example
```ts
import WebSocket from 'ws';
import { SocksProxyAgent } from 'socks-proxy-agent';
const agent = new SocksProxyAgent(
'socks://your-name%40gmail.com:abcdef12345124@br41.nordvpn.com'
);
var socket = new WebSocket('ws://echo.websocket.events', { agent });
socket.on('open', function () {
console.log('"open" event!');
socket.send('hello world');
});
socket.on('message', function (data, flags) {
console.log('"message" event! %j %j', data, flags);
socket.close();
});
```

View File

@@ -0,0 +1,27 @@
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import { SocksProxy } from 'socks';
import { Agent, AgentConnectOpts } from 'agent-base';
import * as net from 'net';
import * as http from 'http';
import { URL } from 'url';
type SocksSocketOptions = Omit<net.TcpNetConnectOpts, 'port' | 'host'>;
export type SocksProxyAgentOptions = Omit<SocksProxy, 'ipaddress' | 'host' | 'port' | 'type' | 'userId' | 'password'> & {
socketOptions?: SocksSocketOptions;
} & http.AgentOptions;
export declare class SocksProxyAgent extends Agent {
static protocols: readonly ["socks", "socks4", "socks4a", "socks5", "socks5h"];
readonly shouldLookup: boolean;
readonly proxy: SocksProxy;
timeout: number | null;
socketOptions: SocksSocketOptions | null;
constructor(uri: string | URL, opts?: SocksProxyAgentOptions);
/**
* Initiates a SOCKS connection to the specified SOCKS proxy server,
* which in turn connects to the specified remote host and port.
*/
connect(req: http.ClientRequest, opts: AgentConnectOpts): Promise<net.Socket>;
}
export {};
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,OAAO,EAAe,UAAU,EAAsB,MAAM,OAAO,CAAC;AACpE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGrD,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAE3B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAoF1B,KAAK,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEvE,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACxC,UAAU,EAEV,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAC9D,GAAG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;CACnC,GAAG,IAAI,CAAC,YAAY,CAAC;AAEtB,qBAAa,eAAgB,SAAQ,KAAK;IACzC,MAAM,CAAC,SAAS,+DAML;IAEX,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,aAAa,EAAE,kBAAkB,GAAG,IAAI,CAAC;gBAE7B,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,sBAAsB;IAY5D;;;OAGG;IACG,OAAO,CACZ,GAAG,EAAE,IAAI,CAAC,aAAa,EACvB,IAAI,EAAE,gBAAgB,GACpB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;CA4EtB"}

View File

@@ -0,0 +1,195 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SocksProxyAgent = void 0;
const socks_1 = require("socks");
const agent_base_1 = require("agent-base");
const debug_1 = __importDefault(require("debug"));
const dns = __importStar(require("dns"));
const net = __importStar(require("net"));
const tls = __importStar(require("tls"));
const url_1 = require("url");
const debug = (0, debug_1.default)('socks-proxy-agent');
const setServernameFromNonIpHost = (options) => {
if (options.servername === undefined &&
options.host &&
!net.isIP(options.host)) {
return {
...options,
servername: options.host,
};
}
return options;
};
function parseSocksURL(url) {
let lookup = false;
let type = 5;
const host = url.hostname;
// From RFC 1928, Section 3: https://tools.ietf.org/html/rfc1928#section-3
// "The SOCKS service is conventionally located on TCP port 1080"
const port = parseInt(url.port, 10) || 1080;
// figure out if we want socks v4 or v5, based on the "protocol" used.
// Defaults to 5.
switch (url.protocol.replace(':', '')) {
case 'socks4':
lookup = true;
type = 4;
break;
// pass through
case 'socks4a':
type = 4;
break;
case 'socks5':
lookup = true;
type = 5;
break;
// pass through
case 'socks': // no version specified, default to 5h
type = 5;
break;
case 'socks5h':
type = 5;
break;
default:
throw new TypeError(`A "socks" protocol must be specified! Got: ${String(url.protocol)}`);
}
const proxy = {
host,
port,
type,
};
if (url.username) {
Object.defineProperty(proxy, 'userId', {
value: decodeURIComponent(url.username),
enumerable: false,
});
}
if (url.password != null) {
Object.defineProperty(proxy, 'password', {
value: decodeURIComponent(url.password),
enumerable: false,
});
}
return { lookup, proxy };
}
class SocksProxyAgent extends agent_base_1.Agent {
constructor(uri, opts) {
super(opts);
const url = typeof uri === 'string' ? new url_1.URL(uri) : uri;
const { proxy, lookup } = parseSocksURL(url);
this.shouldLookup = lookup;
this.proxy = proxy;
this.timeout = opts?.timeout ?? null;
this.socketOptions = opts?.socketOptions ?? null;
}
/**
* Initiates a SOCKS connection to the specified SOCKS proxy server,
* which in turn connects to the specified remote host and port.
*/
async connect(req, opts) {
const { shouldLookup, proxy, timeout } = this;
if (!opts.host) {
throw new Error('No `host` defined!');
}
let { host } = opts;
const { port, lookup: lookupFn = dns.lookup } = opts;
if (shouldLookup) {
// Client-side DNS resolution for "4" and "5" socks proxy versions.
host = await new Promise((resolve, reject) => {
// Use the request's custom lookup, if one was configured:
lookupFn(host, {}, (err, res) => {
if (err) {
reject(err);
}
else {
resolve(res);
}
});
});
}
const socksOpts = {
proxy,
destination: {
host,
port: typeof port === 'number' ? port : parseInt(port, 10),
},
command: 'connect',
timeout: timeout ?? undefined,
// @ts-expect-error the type supplied by socks for socket_options is wider
// than necessary since socks will always override the host and port
socket_options: this.socketOptions ?? undefined,
};
const cleanup = (tlsSocket) => {
req.destroy();
socket.destroy();
if (tlsSocket)
tlsSocket.destroy();
};
debug('Creating socks proxy connection: %o', socksOpts);
const { socket } = await socks_1.SocksClient.createConnection(socksOpts);
debug('Successfully created socks proxy connection');
if (timeout !== null) {
socket.setTimeout(timeout);
socket.on('timeout', () => cleanup());
}
if (opts.secureEndpoint) {
// The proxy is connecting to a TLS server, so upgrade
// this socket connection to a TLS connection.
debug('Upgrading socket connection to TLS');
const tlsSocket = tls.connect({
...omit(setServernameFromNonIpHost(opts), 'host', 'path', 'port'),
socket,
});
tlsSocket.once('error', (error) => {
debug('Socket TLS error', error.message);
cleanup(tlsSocket);
});
return tlsSocket;
}
return socket;
}
}
SocksProxyAgent.protocols = [
'socks',
'socks4',
'socks4a',
'socks5',
'socks5h',
];
exports.SocksProxyAgent = SocksProxyAgent;
function omit(obj, ...keys) {
const ret = {};
let key;
for (key in obj) {
if (!keys.includes(key)) {
ret[key] = obj[key];
}
}
return ret;
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,142 @@
{
"name": "socks-proxy-agent",
"version": "8.0.5",
"description": "A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"author": {
"email": "nathan@tootallnate.net",
"name": "Nathan Rajlich",
"url": "http://n8.io/"
},
"contributors": [
{
"name": "Kiko Beats",
"email": "josefrancisco.verdu@gmail.com"
},
{
"name": "Josh Glazebrook",
"email": "josh@joshglazebrook.com"
},
{
"name": "talmobi",
"email": "talmobi@users.noreply.github.com"
},
{
"name": "Indospace.io",
"email": "justin@indospace.io"
},
{
"name": "Kilian von Pflugk",
"email": "github@jumoog.io"
},
{
"name": "Kyle",
"email": "admin@hk1229.cn"
},
{
"name": "Matheus Fernandes",
"email": "matheus.frndes@gmail.com"
},
{
"name": "Ricky Miller",
"email": "richardkazuomiller@gmail.com"
},
{
"name": "Shantanu Sharma",
"email": "shantanu34@outlook.com"
},
{
"name": "Tim Perry",
"email": "pimterry@gmail.com"
},
{
"name": "Vadim Baryshev",
"email": "vadimbaryshev@gmail.com"
},
{
"name": "jigu",
"email": "luo1257857309@gmail.com"
},
{
"name": "Alba Mendez",
"email": "me@jmendeth.com"
},
{
"name": "Дмитрий Гуденков",
"email": "Dimangud@rambler.ru"
},
{
"name": "Andrei Bitca",
"email": "63638922+andrei-bitca-dc@users.noreply.github.com"
},
{
"name": "Andrew Casey",
"email": "amcasey@users.noreply.github.com"
},
{
"name": "Brandon Ros",
"email": "brandonros1@gmail.com"
},
{
"name": "Dang Duy Thanh",
"email": "thanhdd.it@gmail.com"
},
{
"name": "Dimitar Nestorov",
"email": "8790386+dimitarnestorov@users.noreply.github.com"
}
],
"repository": {
"type": "git",
"url": "https://github.com/TooTallNate/proxy-agents.git",
"directory": "packages/socks-proxy-agent"
},
"keywords": [
"agent",
"http",
"https",
"proxy",
"socks",
"socks4",
"socks4a",
"socks5",
"socks5h"
],
"dependencies": {
"agent-base": "^7.1.2",
"debug": "^4.3.4",
"socks": "^2.8.3"
},
"devDependencies": {
"@types/async-retry": "^1.4.5",
"@types/debug": "^4.1.7",
"@types/dns2": "^2.0.3",
"@types/jest": "^29.5.1",
"@types/node": "^14.18.45",
"async-listen": "^3.0.0",
"async-retry": "^1.3.3",
"cacheable-lookup": "^6.1.0",
"dns2": "^2.1.0",
"jest": "^29.5.0",
"socksv5": "github:TooTallNate/socksv5#fix/dstSock-close-event",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4",
"proxy": "2.2.0",
"tsconfig": "0.0.0"
},
"engines": {
"node": ">= 14"
},
"license": "MIT",
"scripts": {
"build": "tsc",
"test": "jest --env node --verbose --bail test/test.ts",
"test-e2e": "jest --env node --verbose --bail test/e2e.test.ts",
"lint": "eslint . --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
}

60
api.hyungi.net/node_modules/proxy-agent/package.json generated vendored Normal file
View File

@@ -0,0 +1,60 @@
{
"name": "proxy-agent",
"version": "6.3.1",
"description": "Maps proxy protocols to `http.Agent` implementations",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"engines": {
"node": ">= 14"
},
"repository": {
"type": "git",
"url": "https://github.com/TooTallNate/proxy-agents.git",
"directory": "packages/proxy-agent"
},
"keywords": [
"http",
"https",
"socks",
"agent",
"mapping",
"proxy"
],
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
"license": "MIT",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "^4.3.4",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.2",
"lru-cache": "^7.14.1",
"pac-proxy-agent": "^7.0.1",
"proxy-from-env": "^1.1.0",
"socks-proxy-agent": "^8.0.2"
},
"devDependencies": {
"@types/agent-base": "^4.2.0",
"@types/debug": "^4.1.7",
"@types/jest": "^29.5.1",
"@types/node": "^14.18.45",
"@types/proxy-from-env": "^1.0.1",
"@types/ws": "^8.5.4",
"async-listen": "^3.0.0",
"jest": "^29.5.0",
"socksv5": "github:TooTallNate/socksv5#fix/dstSock-close-event",
"ts-jest": "^29.1.0",
"typescript": "^5.0.4",
"ws": "^8.13.0",
"proxy": "2.1.1",
"tsconfig": "0.0.0"
},
"scripts": {
"build": "tsc",
"test": "jest --env node --verbose --bail",
"lint": "eslint . --ext .ts",
"pack": "node ../../scripts/pack.mjs"
}
}