https-proxy-agent
Advanced tools
Comparing version 5.0.1 to 6.0.0
/// <reference types="node" /> | ||
import net from 'net'; | ||
import tls from 'tls'; | ||
import { Url } from 'url'; | ||
import { AgentOptions } from 'agent-base'; | ||
/// <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 { OutgoingHttpHeaders } from 'http'; | ||
import _HttpsProxyAgent from './agent'; | ||
declare function createHttpsProxyAgent(opts: string | createHttpsProxyAgent.HttpsProxyAgentOptions): _HttpsProxyAgent; | ||
declare namespace createHttpsProxyAgent { | ||
interface BaseHttpsProxyAgentOptions { | ||
headers?: OutgoingHttpHeaders; | ||
secureProxy?: boolean; | ||
host?: string | null; | ||
path?: string | null; | ||
port?: string | number | null; | ||
} | ||
export interface HttpsProxyAgentOptions extends AgentOptions, BaseHttpsProxyAgentOptions, Partial<Omit<Url & net.NetConnectOpts & tls.ConnectionOptions, keyof BaseHttpsProxyAgentOptions>> { | ||
} | ||
export type HttpsProxyAgent = _HttpsProxyAgent; | ||
export const HttpsProxyAgent: typeof _HttpsProxyAgent; | ||
export {}; | ||
import { Agent, AgentConnectOpts } from 'agent-base'; | ||
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; | ||
}; | ||
/** | ||
* 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; | ||
connectOpts: net.TcpNetConnectOpts & tls.ConnectionOptions; | ||
get secureProxy(): boolean; | ||
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 = createHttpsProxyAgent; | ||
export {}; | ||
//# sourceMappingURL=index.d.ts.map |
"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 }; | ||
}; | ||
const agent_1 = __importDefault(require("./agent")); | ||
function createHttpsProxyAgent(opts) { | ||
return new agent_1.default(opts); | ||
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 parse_proxy_response_1 = __importDefault(require("./parse-proxy-response")); | ||
const debug = (0, debug_1.default)('https-proxy-agent'); | ||
/** | ||
* 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 { | ||
get secureProxy() { | ||
return isHTTPS(this.proxy.protocol); | ||
} | ||
constructor(proxy, opts) { | ||
super(opts); | ||
this.options = { path: undefined }; | ||
this.proxy = typeof proxy === 'string' ? new 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.secureProxy | ||
? 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, secureProxy } = this; | ||
if (!opts.host) { | ||
throw new TypeError('No "host" provided'); | ||
} | ||
// Create a socket connection to the proxy server. | ||
let socket; | ||
if (secureProxy) { | ||
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); | ||
} | ||
const headers = { ...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.default)(socket); | ||
socket.write(`${payload}\r\n`); | ||
const { statusCode, buffered } = await proxyResponsePromise; | ||
if (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'); | ||
const servername = opts.servername || opts.host; | ||
return tls.connect({ | ||
...omit(opts, 'host', 'path', 'port'), | ||
socket, | ||
servername: net.isIP(servername) ? undefined : servername, | ||
}); | ||
} | ||
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; | ||
} | ||
} | ||
(function (createHttpsProxyAgent) { | ||
createHttpsProxyAgent.HttpsProxyAgent = agent_1.default; | ||
createHttpsProxyAgent.prototype = agent_1.default.prototype; | ||
})(createHttpsProxyAgent || (createHttpsProxyAgent = {})); | ||
module.exports = createHttpsProxyAgent; | ||
HttpsProxyAgent.protocols = ['http', 'https']; | ||
exports.HttpsProxyAgent = HttpsProxyAgent; | ||
function resume(socket) { | ||
socket.resume(); | ||
} | ||
function isHTTPS(protocol) { | ||
return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; | ||
} | ||
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 |
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
import { Readable } from 'stream'; | ||
@@ -8,1 +9,2 @@ export interface ProxyResponse { | ||
export default function parseProxyResponse(socket: Readable): Promise<ProxyResponse>; | ||
//# sourceMappingURL=parse-proxy-response.d.ts.map |
@@ -7,3 +7,3 @@ "use strict"; | ||
const debug_1 = __importDefault(require("debug")); | ||
const debug = debug_1.default('https-proxy-agent:parse-proxy-response'); | ||
const debug = (0, debug_1.default)('https-proxy-agent:parse-proxy-response'); | ||
function parseProxyResponse(socket) { | ||
@@ -55,5 +55,6 @@ return new Promise((resolve, reject) => { | ||
debug('got proxy server response: %o', firstLine); | ||
cleanup(); | ||
resolve({ | ||
statusCode, | ||
buffered | ||
buffered, | ||
}); | ||
@@ -60,0 +61,0 @@ } |
{ | ||
"name": "https-proxy-agent", | ||
"version": "5.0.1", | ||
"version": "6.0.0", | ||
"description": "An HTTP(s) proxy `http.Agent` implementation for HTTPS", | ||
"main": "dist/index", | ||
"types": "dist/index", | ||
"main": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"prebuild": "rimraf dist", | ||
"build": "tsc", | ||
"test": "mocha --reporter spec", | ||
"test-lint": "eslint src --ext .js,.ts", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/TooTallNate/node-https-proxy-agent.git" | ||
"url": "https://github.com/TooTallNate/proxy-agents.git", | ||
"directory": "packages/https-proxy-agent" | ||
}, | ||
@@ -29,29 +23,29 @@ "keywords": [ | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/TooTallNate/node-https-proxy-agent/issues" | ||
}, | ||
"dependencies": { | ||
"agent-base": "6", | ||
"agent-base": "^7.0.0", | ||
"debug": "4" | ||
}, | ||
"devDependencies": { | ||
"@types/async-retry": "^1.4.5", | ||
"@types/debug": "4", | ||
"@types/node": "^12.12.11", | ||
"@typescript-eslint/eslint-plugin": "1.6.0", | ||
"@typescript-eslint/parser": "1.1.0", | ||
"eslint": "5.16.0", | ||
"eslint-config-airbnb": "17.1.0", | ||
"eslint-config-prettier": "4.1.0", | ||
"eslint-import-resolver-typescript": "1.1.1", | ||
"eslint-plugin-import": "2.16.0", | ||
"eslint-plugin-jsx-a11y": "6.2.1", | ||
"eslint-plugin-react": "7.12.4", | ||
"mocha": "^6.2.2", | ||
"proxy": "1", | ||
"rimraf": "^3.0.0", | ||
"typescript": "^3.5.3" | ||
"@types/jest": "^29.5.1", | ||
"@types/node": "^14.18.43", | ||
"async-listen": "^2.1.0", | ||
"async-retry": "^1.3.3", | ||
"jest": "^29.5.0", | ||
"ts-jest": "^29.1.0", | ||
"typescript": "^5.0.4", | ||
"proxy": "2.0.0", | ||
"tsconfig": "0.0.0" | ||
}, | ||
"engines": { | ||
"node": ">= 6" | ||
"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" | ||
} | ||
} | ||
} |
https-proxy-agent | ||
================ | ||
### An HTTP(s) proxy `http.Agent` implementation for HTTPS | ||
[![Build Status](https://github.com/TooTallNate/node-https-proxy-agent/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-https-proxy-agent/actions?workflow=Node+CI) | ||
@@ -17,13 +16,2 @@ This module provides an `http.Agent` implementation that connects to a specified | ||
Installation | ||
------------ | ||
Install with `npm`: | ||
``` bash | ||
$ npm install https-proxy-agent | ||
``` | ||
Examples | ||
@@ -34,21 +22,9 @@ -------- | ||
``` js | ||
var url = require('url'); | ||
var https = require('https'); | ||
var HttpsProxyAgent = require('https-proxy-agent'); | ||
```ts | ||
import * as https from 'https'; | ||
import { HttpsProxyAgent } from 'https-proxy-agent'; | ||
// HTTP/HTTPS proxy to connect to | ||
var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; | ||
console.log('using proxy server %j', proxy); | ||
const agent = new HttpsProxyAgent('http://168.63.76.32:3128'); | ||
// HTTPS endpoint for the proxy to connect to | ||
var endpoint = process.argv[2] || 'https://graph.facebook.com/tootallnate'; | ||
console.log('attempting to GET %j', endpoint); | ||
var options = url.parse(endpoint); | ||
// create an instance of the `HttpsProxyAgent` class with the proxy server information | ||
var agent = new HttpsProxyAgent(proxy); | ||
options.agent = agent; | ||
https.get(options, function (res) { | ||
https.get('https://example.com', { agent }, (res) => { | ||
console.log('"response" event!', res.headers); | ||
@@ -61,24 +37,9 @@ res.pipe(process.stdout); | ||
``` js | ||
var url = require('url'); | ||
var WebSocket = require('ws'); | ||
var HttpsProxyAgent = require('https-proxy-agent'); | ||
```ts | ||
import WebSocket from 'ws'; | ||
import { HttpsProxyAgent } from 'https-proxy-agent'; | ||
// HTTP/HTTPS proxy to connect to | ||
var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; | ||
console.log('using proxy server %j', proxy); | ||
const agent = new HttpsProxyAgent('http://168.63.76.32:3128'); | ||
const socket = new WebSocket('ws://echo.websocket.org', { agent }); | ||
// WebSocket endpoint for the proxy to connect to | ||
var endpoint = process.argv[2] || 'ws://echo.websocket.org'; | ||
var parsed = url.parse(endpoint); | ||
console.log('attempting to connect to WebSocket %j', endpoint); | ||
// create an instance of the `HttpsProxyAgent` class with the proxy server information | ||
var options = url.parse(proxy); | ||
var agent = new HttpsProxyAgent(options); | ||
// finally, initiate the WebSocket connection | ||
var socket = new WebSocket(endpoint, { agent: agent }); | ||
socket.on('open', function () { | ||
@@ -98,3 +59,3 @@ console.log('"open" event!'); | ||
### new HttpsProxyAgent(Object options) | ||
### new HttpsProxyAgent(proxy: string | URL, options?: HttpsProxyAgentOptions) | ||
@@ -105,12 +66,11 @@ The `HttpsProxyAgent` class implements an `http.Agent` subclass that connects | ||
The `options` argument may either be a string URI of the proxy server to use, or an | ||
"options" object with more specific properties: | ||
The `proxy` argument is the URL for the proxy server. | ||
* `host` - String - Proxy host to connect to (may use `hostname` as well). Required. | ||
* `port` - Number - Proxy port to connect to. Required. | ||
* `protocol` - String - If `https:`, then use TLS to connect to the proxy. | ||
* `headers` - Object - Additional HTTP headers to be sent on the HTTP CONNECT method. | ||
* Any other options given are passed to the `net.connect()`/`tls.connect()` functions. | ||
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. | ||
License | ||
@@ -117,0 +77,0 @@ ------- |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
31702
11
462
1
98
5
+ Addedagent-base@7.1.1(transitive)
- Removedagent-base@6.0.2(transitive)
Updatedagent-base@^7.0.0