diff --git a/api.d.ts b/api.d.ts index d86f050..4a1f89d 100644 --- a/api.d.ts +++ b/api.d.ts @@ -12,6 +12,7 @@ export interface XHROptions { data?: string; strictSSL?: boolean; followRedirects?: number; + agent?: HttpProxyAgent | HttpsProxyAgent; } export interface XHRResponse { @@ -29,6 +30,10 @@ export interface XHRConfigure { (proxyUrl: string, strictSSL: boolean): void; } +export type HttpProxyAgent = import('http-proxy-agent').HttpProxyAgent; + +export type HttpsProxyAgent = import('https-proxy-agent').HttpsProxyAgent; + export type Headers = { [header: string]: string | string[] | undefined }; export declare const configure: XHRConfigure; diff --git a/src/node/main.ts b/src/node/main.ts index 86553c4..8b67bc4 100644 --- a/src/node/main.ts +++ b/src/node/main.ts @@ -137,6 +137,7 @@ function request(options: XHROptions): Promise { let opts: https.RequestOptions = { hostname: endpoint.hostname, + agent: options.agent ? options.agent : false, port: endpoint.port ? parseInt(endpoint.port) : (endpoint.protocol === 'https:' ? 443 : 80), path: endpoint.path, method: options.type || 'GET', @@ -248,7 +249,8 @@ function getProxyAgent(rawRequestURL: string, options: ProxyOptions = {}): any { host: proxyEndpoint.hostname, port: Number(proxyEndpoint.port), auth: proxyEndpoint.auth, - rejectUnauthorized: (typeof options.strictSSL === 'boolean') ? options.strictSSL : true + rejectUnauthorized: (typeof options.strictSSL === 'boolean') ? options.strictSSL : true, + protocol: proxyEndpoint.protocol }; return requestURL.protocol === 'http:' ? createHttpProxyAgent(opts) : createHttpsProxyAgent(opts); diff --git a/src/test/test.ts b/src/test/test.ts index 365c849..c221302 100644 --- a/src/test/test.ts +++ b/src/test/test.ts @@ -64,6 +64,28 @@ test('proxy http to http', async t => { proxy.close(); }); +test('invalid proxy http to http', async t => { + const server = await createServer(); + const proxy = await createProxy(); + server.on('request', (req, res) => res.end('ok')); + + const invalidProxyAddress = { + address: '192.168.29.165', + port: '808' + } + + configure(`http://${invalidProxyAddress.address}:${invalidProxyAddress.port}`, false); + + const serverAddress = server.address() as AddressInfo; + + await xhr({ url: `http://${serverAddress.address}:${serverAddress.port}` }).catch((response) => { + t.deepEqual(response.responseText, 'Unable to connect to http://' + `${serverAddress.address}` + ':' + `${serverAddress.port}` + ' through a proxy . Error: connect ECONNREFUSED 192.168.29.165:808'); + t.is(response.status, 404); + }); + server.close(); + proxy.close(); +}); + test('proxy https to https', async t => { const server = await createSecureServer(); @@ -72,7 +94,7 @@ test('proxy https to https', async t => { const proxyAddress = proxy.address() as AddressInfo; - configure(`http://${proxyAddress.address}:${proxyAddress.port}`, false); + configure(`https://${proxyAddress.address}:${proxyAddress.port}`, false); const serverAddress = server.address() as AddressInfo; @@ -88,13 +110,13 @@ test('proxy https to https', async t => { test('relative redirect', async t => { const server = await createServer(); - server.on('request', (req:IncomingMessage, res: ServerResponse) => { - if(req.url.includes('/foo')) { + server.on('request', (req: IncomingMessage, res: ServerResponse) => { + if (req.url.includes('/foo')) { res.setHeader('Location', '/bar'); res.statusCode = 301; res.end(); } - if(req.url.includes('/bar')){ + if (req.url.includes('/bar')) { res.end('Bar'); } });