123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- "use strict";
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- const net_1 = __importDefault(require("net"));
- const tls_1 = __importDefault(require("tls"));
- const once_1 = __importDefault(require("@tootallnate/once"));
- const crypto_1 = __importDefault(require("crypto"));
- const get_uri_1 = __importDefault(require("get-uri"));
- const debug_1 = __importDefault(require("debug"));
- const raw_body_1 = __importDefault(require("raw-body"));
- const url_1 = require("url");
- 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 pac_resolver_1 = __importDefault(require("pac-resolver"));
- const agent_base_1 = require("agent-base");
- const debug = debug_1.default('pac-proxy-agent');
- class PacProxyAgent extends agent_base_1.Agent {
- constructor(uri, opts = {}) {
- super(opts);
- this.clearResolverPromise = () => {
- this.resolverPromise = undefined;
- };
- debug('Creating PacProxyAgent with URI %o and options %o', uri, opts);
-
- this.uri = uri.replace(/^pac\+/i, '');
- this.opts = Object.assign({}, opts);
- this.cache = undefined;
- this.resolver = undefined;
- this.resolverHash = '';
- this.resolverPromise = undefined;
-
- if (!this.opts.filename) {
- this.opts.filename = uri;
- }
- }
-
- getResolver() {
- if (!this.resolverPromise) {
- this.resolverPromise = this.loadResolver();
- this.resolverPromise.then(this.clearResolverPromise, this.clearResolverPromise);
- }
- return this.resolverPromise;
- }
- loadResolver() {
- return __awaiter(this, void 0, void 0, function* () {
- try {
-
- const code = yield this.loadPacFile();
-
- const hash = crypto_1.default
- .createHash('sha1')
- .update(code)
- .digest('hex');
- if (this.resolver && this.resolverHash === hash) {
- debug('Same sha1 hash for code - contents have not changed, reusing previous proxy resolver');
- return this.resolver;
- }
-
- debug('Creating new proxy resolver instance');
- this.resolver = pac_resolver_1.default(code, this.opts);
-
- this.resolverHash = hash;
- return this.resolver;
- }
- catch (err) {
- if (this.resolver && err.code === 'ENOTMODIFIED') {
- debug('Got ENOTMODIFIED response, reusing previous proxy resolver');
- return this.resolver;
- }
- throw err;
- }
- });
- }
-
- loadPacFile() {
- return __awaiter(this, void 0, void 0, function* () {
- debug('Loading PAC file: %o', this.uri);
- const rs = yield get_uri_1.default(this.uri, { cache: this.cache });
- debug('Got `Readable` instance for URI');
- this.cache = rs;
- const buf = yield raw_body_1.default(rs);
- debug('Read %o byte PAC file from URI', buf.length);
- return buf.toString('utf8');
- });
- }
-
- callback(req, opts) {
- return __awaiter(this, void 0, void 0, function* () {
- const { secureEndpoint } = opts;
-
-
- const resolver = yield this.getResolver();
-
- const defaultPort = secureEndpoint ? 443 : 80;
- let path = req.path;
- let search = null;
- const firstQuestion = path.indexOf('?');
- if (firstQuestion !== -1) {
- search = path.substring(firstQuestion);
- path = path.substring(0, firstQuestion);
- }
- const urlOpts = Object.assign(Object.assign({}, opts), { protocol: secureEndpoint ? 'https:' : 'http:', pathname: path, search,
-
- hostname: opts.host, host: null, href: null,
-
- port: defaultPort === opts.port ? null : opts.port });
- const url = url_1.format(urlOpts);
- debug('url: %o', url);
- let result = yield resolver(url);
-
- if (!result) {
- result = 'DIRECT';
- }
- const proxies = String(result)
- .trim()
- .split(/\s*;\s*/g)
- .filter(Boolean);
- if (this.opts.fallbackToDirect && !proxies.includes('DIRECT')) {
- proxies.push('DIRECT');
- }
- for (const proxy of proxies) {
- let agent = null;
- let socket = null;
- const [type, target] = proxy.split(/\s+/);
- debug('Attempting to use proxy: %o', proxy);
- if (type === 'DIRECT') {
-
- socket = secureEndpoint ? tls_1.default.connect(opts) : net_1.default.connect(opts);
- }
- else if (type === 'SOCKS' || type === 'SOCKS5') {
-
- agent = new socks_proxy_agent_1.SocksProxyAgent(`socks://${target}`);
- }
- else if (type === 'SOCKS4') {
-
- agent = new socks_proxy_agent_1.SocksProxyAgent(`socks4a://${target}`);
- }
- else if (type === 'PROXY' ||
- type === 'HTTP' ||
- type === 'HTTPS') {
-
-
- const proxyURL = `${type === 'HTTPS' ? 'https' : 'http'}://${target}`;
- const proxyOpts = Object.assign(Object.assign({}, this.opts), url_1.parse(proxyURL));
- if (secureEndpoint) {
- agent = new https_proxy_agent_1.HttpsProxyAgent(proxyOpts);
- }
- else {
- agent = new http_proxy_agent_1.HttpProxyAgent(proxyOpts);
- }
- }
- try {
- if (socket) {
-
- yield once_1.default(socket, 'connect');
- req.emit('proxy', { proxy, socket });
- return socket;
- }
- if (agent) {
- const s = yield agent.callback(req, opts);
- req.emit('proxy', { proxy, socket: s });
- return s;
- }
- throw new Error(`Could not determine proxy type for: ${proxy}`);
- }
- catch (err) {
- debug('Got error for proxy %o: %o', proxy, err);
- req.emit('proxy', { proxy, error: err });
- }
- }
- throw new Error(`Failed to establish a socket connection to proxies: ${JSON.stringify(proxies)}`);
- });
- }
- }
- exports.default = PacProxyAgent;
|