From 6cf13bac84c6996f7e0bf1fcbca46a24be7b8735 Mon Sep 17 00:00:00 2001 From: Jonathan Foster Date: Thu, 3 Dec 2020 02:36:50 -0500 Subject: [PATCH] Protocol not parsed when setting proxy config from env vars (#3070) * Fixing proxy protocol config when parsed from env vars * Adding instructions to specify proxy protocol when setting proxy config * Moved HTTPS proxy config instruction closer to example * Clear https_proxy env var so as to not impact other tests --- README.md | 4 +- lib/adapters/http.js | 4 +- test/unit/adapters/cert.pem | 17 ++++++ test/unit/adapters/http.js | 102 ++++++++++++++++++++++++++++++++++++ test/unit/adapters/key.pem | 27 ++++++++++ 5 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 test/unit/adapters/cert.pem create mode 100644 test/unit/adapters/key.pem diff --git a/README.md b/README.md index 620fecab5e..44264f6c13 100755 --- a/README.md +++ b/README.md @@ -422,7 +422,7 @@ These are the available config options for making requests. Only the `url` is re httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), - // `proxy` defines the hostname and port of the proxy server. + // `proxy` defines the hostname, port, and protocol of the proxy server. // You can also define your proxy using the conventional `http_proxy` and // `https_proxy` environment variables. If you are using environment variables // for your proxy configuration, you can also define a `no_proxy` environment @@ -432,7 +432,9 @@ These are the available config options for making requests. Only the `url` is re // supplies credentials. // This will set an `Proxy-Authorization` header, overwriting any existing // `Proxy-Authorization` custom headers you have set using `headers`. + // If the proxy server uses HTTPS, then you must set the protocol to `https`. proxy: { + protocol: 'https', host: '127.0.0.1', port: 9000, auth: { diff --git a/lib/adapters/http.js b/lib/adapters/http.js index 77174e2668..f32241f77e 100755 --- a/lib/adapters/http.js +++ b/lib/adapters/http.js @@ -151,11 +151,11 @@ module.exports = function httpAdapter(config) { }); } - if (shouldProxy) { proxy = { host: parsedProxyUrl.hostname, - port: parsedProxyUrl.port + port: parsedProxyUrl.port, + protocol: parsedProxyUrl.protocol }; if (parsedProxyUrl.auth) { diff --git a/test/unit/adapters/cert.pem b/test/unit/adapters/cert.pem new file mode 100644 index 0000000000..42dcc29b0d --- /dev/null +++ b/test/unit/adapters/cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICpDCCAYwCCQDbqELLwgbPdDANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAls +b2NhbGhvc3QwHhcNMjAwNjI2MjIxMTQ3WhcNNDcxMTExMjIxMTQ3WjAUMRIwEAYD +VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD6 +Ogt99/dZ0UgbCuVV1RZ9n28Ov3DzrJCkjperQoXomIq3Fr4RUI1a2rwe3mtl3UzE +1IVZVvWPGdEsEQHwXfAsP/jFGTwI3HDyOhcqzFQSKsjvqJWYkOOb+2r3SBrFlRZW +09k/3lC+hx2XtuuG68u4Xgn3AlUvm2vplgCN7eiYcGeNwVuf2eHdOqTRTqiYCZLi +T8GtdYMDXOrwsGZs/jUKd9U0ar/lqwMhmw07yzlVDM2MWM2tyq/asQ7Sf7vuoMFu +oAtDJ3E+bK1k/7SNhdyP4RonhyUCkWG+mzoKDS1qgXroTiQSDUksAvOCTcj8BNIT +ee+Lcn9FaTKNJiKiU9q/AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFi5ZpaUj+mU +dsgOka+j2/njgNXux3cOjhm7z/N7LeTuDENAOrYa5b+j5JX/YM7RKHrkbXHsQbfs +GB3ufH6QhSiCd/AdsXp/TbCE/8gdq8ykkjwVP1bvBle9oPH7x1aO/WP/odsepYUv +o9aOZW4iNQVmwamU62ezglf3QD7HPeE4LnZueaFtuzRoC+aWT9v0MIeUPJLe3WDQ +FEySwUuthMDJEv92/TeK0YOiunmseCu2mvdiDj6E3C9xa5q2DWgl+msu7+bPgvYO +GuWaoNeQQGk7ebBO3Hk3IyaGx6Cbd8ty+YaZW7dUT+m7KCs1VkxdcDMjZJVWiJy4 +4HcEcKboG4Y= +-----END CERTIFICATE----- diff --git a/test/unit/adapters/http.js b/test/unit/adapters/http.js index 9c3fcd7fbf..7fdeddf8d1 100644 --- a/test/unit/adapters/http.js +++ b/test/unit/adapters/http.js @@ -1,5 +1,6 @@ var axios = require('../../../index'); var http = require('http'); +var https = require('https'); var net = require('net'); var url = require('url'); var zlib = require('zlib'); @@ -489,6 +490,57 @@ describe('supports http with nodejs', function () { }); }); + it('should support HTTPS proxies', function (done) { + var options = { + key: fs.readFileSync(path.join(__dirname, 'key.pem')), + cert: fs.readFileSync(path.join(__dirname, 'cert.pem')) + }; + + server = https.createServer(options, function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=UTF-8'); + res.end('12345'); + }).listen(4444, function () { + proxy = https.createServer(options, function (request, response) { + var parsed = url.parse(request.url); + var opts = { + host: parsed.hostname, + port: parsed.port, + path: parsed.path, + protocol: parsed.protocol, + rejectUnauthorized: false + }; + + https.get(opts, function (res) { + var body = ''; + res.on('data', function (data) { + body += data; + }); + res.on('end', function () { + response.setHeader('Content-Type', 'text/html; charset=UTF-8'); + response.end(body + '6789'); + }); + }); + }).listen(4000, function () { + axios.get('https://localhost:4444/', { + proxy: { + host: 'localhost', + port: 4000, + protocol: 'https' + }, + httpsAgent: new https.Agent({ + rejectUnauthorized: false + }) + }).then(function (res) { + assert.equal(res.data, '123456789', 'should pass through proxy'); + done(); + }).catch(function (err) { + assert.fail(err); + done() + }); + }); + }); + }); + it('should not pass through disabled proxy', function (done) { // set the env variable process.env.http_proxy = 'http://does-not-exists.example.com:4242/'; @@ -542,6 +594,56 @@ describe('supports http with nodejs', function () { }); }); + it('should support HTTPS proxy set via env var', function (done) { + var options = { + key: fs.readFileSync(path.join(__dirname, 'key.pem')), + cert: fs.readFileSync(path.join(__dirname, 'cert.pem')) + }; + + server = https.createServer(options, function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=UTF-8'); + res.end('12345'); + }).listen(4444, function () { + proxy = https.createServer(options, function (request, response) { + var parsed = url.parse(request.url); + var opts = { + host: parsed.hostname, + port: parsed.port, + path: parsed.path, + protocol: parsed.protocol, + rejectUnauthorized: false + }; + + https.get(opts, function (res) { + var body = ''; + res.on('data', function (data) { + body += data; + }); + res.on('end', function () { + response.setHeader('Content-Type', 'text/html; charset=UTF-8'); + response.end(body + '6789'); + }); + }); + }).listen(4000, function () { + process.env.https_proxy = 'https://localhost:4000/'; + + axios.get('https://localhost:4444/', { + httpsAgent: new https.Agent({ + rejectUnauthorized: false + }) + }).then(function (res) { + assert.equal(res.data, '123456789', 'should pass through proxy'); + done(); + }).catch(function (err) { + assert.fail(err); + done() + }).finally(function () { + process.env.https_proxy = '' + }); + }); + }); + }); + it('should not use proxy for domains in no_proxy', function (done) { server = http.createServer(function (req, res) { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); diff --git a/test/unit/adapters/key.pem b/test/unit/adapters/key.pem new file mode 100644 index 0000000000..9ce05bf90f --- /dev/null +++ b/test/unit/adapters/key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA+joLfff3WdFIGwrlVdUWfZ9vDr9w86yQpI6Xq0KF6JiKtxa+ +EVCNWtq8Ht5rZd1MxNSFWVb1jxnRLBEB8F3wLD/4xRk8CNxw8joXKsxUEirI76iV +mJDjm/tq90gaxZUWVtPZP95Qvocdl7brhuvLuF4J9wJVL5tr6ZYAje3omHBnjcFb +n9nh3Tqk0U6omAmS4k/BrXWDA1zq8LBmbP41CnfVNGq/5asDIZsNO8s5VQzNjFjN +rcqv2rEO0n+77qDBbqALQydxPmytZP+0jYXcj+EaJ4clApFhvps6Cg0taoF66E4k +Eg1JLALzgk3I/ATSE3nvi3J/RWkyjSYiolPavwIDAQABAoIBAEbMi5ndwjfAlkVI +hPEPNKjgpnymwB/CEL7utY04akkQeBcrsSWXBBfT0exuBDczMVhzxTMs/pe5t0xf +l4vaGG18wDeMV0cukCqJMyrh21u0jVv5+DHNtQjaTz6eQSzsbQCuOkbu8SuncUEO ++X8YUnDc8rbYCyBIOnVCAvAlg201uW0G5G9NEwJOu6cAKMKkogdHqv+FRX96C5hm +gtbGEzpGV2vVClgMwMcX49ucluZvqLvit/yehNVd0VOtW/kuLup4R6q0abHRapDd +95rJAhPvar4mzP+UgJrGQ9hozqhizDthBjnsmGeMBUiBCkay7OXIZpvLoCpQkti1 +WIWuikkCgYEA/oZqq71RT1nPuI7rlcjx3AeWe2EUQtKhQMJBiPx5eLLP6gII8+v2 +pD1qlmJM2eyIK0lzuskLIulTAA5Z+ejORDbvmn/DdT0CSvdrUFrcvnrRQnt2M5M2 +9VDRp6nvPE0H4kRZJrtITyLn0dv5ABf2L32i4dPCMePjKjSUygJSHrsCgYEA+61A +cIqch/lrQTk8hG7Y6p0EJzSInFVaKuZoMYpLhlDQcVvSDIQbGgRAN6BKTdxeQ+tK +hSxBSm2mze11aHig8GBGgdBFLaJOZRo6G+2fl+s1t1FCHfsaFhHwheZJONHMpKKd +Qm/7L/V35QV9YG0lPZ01TM6d5lXuKsmUNvBJTc0CgYASYajAgGqn3WeX/5JZ/eoh +ptaiUG+DJ+0HXUAYYYtwQRGs57q3yvnEAL963tyH/IIVBjf6bFyGh+07ms26s6p5 +2LHTKZj3FZHd0iKI6hb5FquYLoxpyx7z9oM9pZMmerWwDJmXp3zgYjf1uvovnItm +AJ/LyVxD+B5GxQdd028U0wKBgG4OllZglxDzJk7wa6FyI9N89Fr8oxzSSkrmVPwN +APfskSpxP8qPXpai8z4gDz47NtG2q/DOqIKWrtHwnF4iGibjwxFzdTz+dA/MR0r9 +P8QcbHIMy7/2lbK/B5JWYQDC5h28qs5pz8tqKZLyMqCfOiDWhX9f/zbBrxPw8KqR +q0ylAoGAL/0kemA/Tmxpwmp0S0oCqnA4gbCgS7qnApxB09xTewc/tuvraXc3Mzea +EvqDXLXK0R7O4E3vo0Mr23SodRVlFPevsmUUJLPJMJcxdfnSJgX+qE/UC8Ux+UMi +eYufYRDYSslfL2rt9D7abnnbqSfsHymJKukWpElIgJTklQUru4k= +-----END RSA PRIVATE KEY-----