diff --git a/index.js b/index.js index 0cdcc00..e7d80a9 100644 --- a/index.js +++ b/index.js @@ -68,6 +68,7 @@ function requestAsEventEmitter(opts) { const ee = new EventEmitter(); const requestUrl = opts.href || urlLib.resolve(urlLib.format(opts), opts.path); const redirects = []; + const agents = typeof opts.agent === 'object' ? opts.agent : null; let retryCount = 0; let redirectUrl; let uploadBodySize; @@ -81,6 +82,11 @@ function requestAsEventEmitter(opts) { let fn = opts.protocol === 'https:' ? https : http; + if (agents) { + const protocolName = opts.protocol === 'https:' ? 'https' : 'http'; + opts.agent = agents[protocolName] || opts.agent; + } + if (opts.useElectronNet && process.versions.electron) { const electron = require('electron'); fn = electron.net || electron.remote.net; @@ -338,6 +344,7 @@ function asPromise(opts) { ee.on('error', reject); ee.on('uploadProgress', proxy.emit.bind(proxy, 'uploadProgress')); ee.on('downloadProgress', proxy.emit.bind(proxy, 'downloadProgress')); + ee.on('redirect', proxy.emit.bind(proxy, 'redirect')); }); const promise = timeoutFn(cancelable); diff --git a/readme.md b/readme.md index 31c5d11..b9374bb 100644 --- a/readme.md +++ b/readme.md @@ -403,6 +403,21 @@ got('todomvc.com', { }); ``` +If you require different agents for different protocols, you can pass a map of agents to the `agent` option. This is necessary because a request to one protocol might redirect to another. In such a scenario, `got` will switch over to the right protocol agent for you. + +```js +const got = require('got'); +const HttpAgent = require('agentkeepalive'); +const HttpsAgent = HttpAgent.HttpsAgent; + +got('sindresorhus.com', { + agent: { + http: new HttpAgent(), + https: new HttpsAgent() + } +}); +``` + ## Cookies diff --git a/test/redirects.js b/test/redirects.js index 5306573..bf05b64 100644 --- a/test/redirects.js +++ b/test/redirects.js @@ -1,6 +1,9 @@ +import {Agent as HttpAgent} from 'http'; +import {Agent as HttpsAgent} from 'https'; import test from 'ava'; import pem from 'pem'; import pify from 'pify'; +import sinon from 'sinon'; import got from '..'; import {createServer, createSSLServer} from './helpers/server'; @@ -35,12 +38,22 @@ test.before('setup', async () => { const cert = keys.certificate; https = await createSSLServer({key, cert}); // eslint-disable-line object-property-newline + http = await createServer(); + + // HTTPS Handlers https.on('/', (req, res) => { res.end('https'); }); - http = await createServer(); + https.on('/httpsToHttp', (req, res) => { + res.writeHead(302, { + location: http.url + }); + res.end(); + }); + + // HTTP Handlers http.on('/', (req, res) => { res.end('reached'); @@ -173,6 +186,29 @@ test('redirects from http to https works', async t => { t.truthy((await got(`${http.url}/httpToHttps`, {rejectUnauthorized: false})).body); }); +test('redirects from https to http works', async t => { + t.truthy((await got(`${https.url}/httpsToHttp`, {rejectUnauthorized: false})).body); +}); + +test('redirects from https to http works with an agent object', async t => { + const httpAgent = new HttpAgent({keepAlive: true}); + const httpsAgent = new HttpsAgent({keepAlive: true}); + const httpSpy = sinon.spy(httpAgent, 'addRequest'); + const httpsSpy = sinon.spy(httpsAgent, 'addRequest'); + t.truthy((await got(`${https.url}/httpsToHttp`, { + rejectUnauthorized: false, + agent: { + http: httpAgent, + https: httpsAgent + } + })).body); + t.true(httpSpy.calledOnce); + t.true(httpsSpy.calledOnce); + // Make sure to close all open sockets + httpAgent.destroy(); + httpsAgent.destroy(); +}); + test('redirects works with lowercase method', async t => { const body = (await got(`${http.url}/relative`, {method: 'head'})).body; t.is(body, '');