diff --git a/src/chain.ts b/src/chain.ts index 14ce2b3c..73c661ef 100644 --- a/src/chain.ts +++ b/src/chain.ts @@ -1,4 +1,5 @@ import http from 'http'; +import https from 'https'; import dns from 'dns'; import { URL } from 'url'; import { EventEmitter } from 'events'; @@ -80,7 +81,8 @@ export const chain = ( options.headers.push('proxy-authorization', getBasicAuthorizationHeader(proxy)); } - const client = http.request(proxy.origin, options as unknown as http.ClientRequestArgs); + const fn = proxy.protocol === 'https:' ? https.request : http.request; + const client = fn(proxy.origin, options as unknown as http.ClientRequestArgs); client.on('connect', (response, targetSocket, clientHead) => { countTargetBytes(sourceSocket, targetSocket); diff --git a/src/server.ts b/src/server.ts index fc2f9c89..4b4a8fdb 100644 --- a/src/server.ts +++ b/src/server.ts @@ -453,9 +453,9 @@ export class Server extends EventEmitter { throw new Error(`Invalid "upstreamProxyUrl" provided: ${error} (was "${funcResult.upstreamProxyUrl}"`); } - if (!['http:', ...SOCKS_PROTOCOLS].includes(handlerOpts.upstreamProxyUrlParsed.protocol)) { + if (!['http:', 'https:', ...SOCKS_PROTOCOLS].includes(handlerOpts.upstreamProxyUrlParsed.protocol)) { // eslint-disable-next-line max-len - throw new Error(`Invalid "upstreamProxyUrl" provided: URL must have one of the following protocols: "http", ${SOCKS_PROTOCOLS.map((p) => `"${p.replace(':', '')}"`).join(', ')} (was "${funcResult.upstreamProxyUrl}")`); + throw new Error(`Invalid "upstreamProxyUrl" provided: URL must have one of the following protocols: "http", "https", ${SOCKS_PROTOCOLS.map((p) => `"${p.replace(':', '')}"`).join(', ')} (was "${funcResult.upstreamProxyUrl}")`); } } diff --git a/test/server.js b/test/server.js index 534f5c8c..9086b437 100644 --- a/test/server.js +++ b/test/server.js @@ -9,6 +9,7 @@ const util = require('util'); const { expect, assert } = require('chai'); const proxy = require('proxy'); const http = require('http'); +const https = require('https'); const portastic = require('portastic'); const request = require('request'); const WebSocket = require('faye-websocket'); @@ -1337,6 +1338,45 @@ it('supports localAddress', async () => { } }); +it('supports https proxy relay', async () => { + const target = https.createServer(() => { + }); + target.listen(() => { + }); + + const proxyServer = new ProxyChain.Server({ + port: 6666, + prepareRequestFunction: () => { + console.log(`https://localhost:${target.address().port}`); + return { + upstreamProxyUrl: `https://localhost:${target.address().port}`, + }; + }, + }); + let proxyServerError = false; + proxyServer.on('requestFailed', () => { + // requestFailed will be called if we pass an invalid proxy url + proxyServerError = true; + }) + + await proxyServer.listen(); + + try { + await requestPromised({ + url: 'https://www.google.com', + proxy: 'http://localhost:6666', + strictSSL: false, + }); + } catch (e) { + // the request will fail with the following error: + // Error: tunneling socket could not be established, statusCode=599 + } + expect(proxyServerError).to.be.equal(false); + + proxyServer.close(); + target.close(); +}); + it('supports custom CONNECT server handler', async () => { const server = new Server({ port: 0,