From: Jakub Pawlowicz Date: Sun, 16 Aug 2015 11:17:55 +0000 (+0100) Subject: Adds inferring proxy settings from environment variables. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=7d99a861bfaa50f580825fff4698849d687c5a18;p=clean-css.git Adds inferring proxy settings from environment variables. It is common for *nix and Windows programs to use to HTTP_PROXY variable to identify proxy settings. So do we, e.g. ```bash HTTP_PROXY=http://proxy-host:proxy-port cleancss styles.css ``` --- diff --git a/History.md b/History.md index 4a20e7fc..cf383db7 100644 --- a/History.md +++ b/History.md @@ -2,6 +2,7 @@ ================== * Adds unit compatibility switches to disable length optimizations. +* Adds inferring proxy settings from HTTP_PROXY environment variable. * Unifies wrappers for simple & advanced optimizations. * Fixed issue [#599](https://github.com/jakubpawlowicz/clean-css/issues/599) - support for inlined source maps. * Fixed issue [#612](https://github.com/jakubpawlowicz/clean-css/issues/612) - adds HTTP proxy support. diff --git a/lib/clean.js b/lib/clean.js index aa47cd11..1ef29cb1 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -28,6 +28,9 @@ var Validator = require('./properties/validator'); var fs = require('fs'); var path = require('path'); +var url = require('url'); + +var override = require('./utils/object').override; var DEFAULT_TIMEOUT = 5000; @@ -60,7 +63,11 @@ var CleanCSS = module.exports = function CleanCSS(options) { }; this.options.inliner.timeout = this.options.inliner.timeout || DEFAULT_TIMEOUT; - this.options.inliner.request = this.options.inliner.request || {}; + this.options.inliner.request = override( + /* jshint camelcase: false */ + proxyOptionsFrom(process.env.HTTP_PROXY || process.env.http_proxy), + this.options.inliner.request || {} + ); }; function missingDirectory(filepath) { @@ -71,6 +78,15 @@ function presentDirectory(filepath) { return fs.existsSync(filepath) && fs.statSync(filepath).isDirectory(); } +function proxyOptionsFrom(httpProxy) { + return httpProxy ? + { + hostname: url.parse(httpProxy).hostname, + port: parseInt(url.parse(httpProxy).port) + } : + {}; +} + CleanCSS.prototype.minify = function (data, callback) { var context = { stats: {}, diff --git a/test/binary-test.js b/test/binary-test.js index d3f345a4..b60c9aca 100644 --- a/test/binary-test.js +++ b/test/binary-test.js @@ -3,7 +3,9 @@ var assert = require('assert'); var exec = require('child_process').exec; var fs = require('fs'); var http = require('http'); +var httpProxy = require('http-proxy'); var path = require('path'); +var url = require('url'); var SourceMapConsumer = require('source-map').SourceMapConsumer; var isWindows = process.platform == 'win32'; @@ -333,6 +335,39 @@ vows.describe('./bin/cleancss') } }) }) + .addBatch({ + 'HTTP proxy': unixOnlyContext({ + topic: function () { + var self = this; + this.proxied = false; + + var proxy = httpProxy.createProxyServer(); + this.proxyServer = http.createServer(function (req, res) { + self.proxied = true; + proxy.web(req, res, { target: 'http://' + url.parse(req.url).host }, function () {}); + }); + this.proxyServer.listen(8081); + + this.server = http.createServer(function (req, res) { + res.writeHead(200); + res.end('a{color:red}'); + }); + this.server.listen(8080); + + exec('echo "@import url(http://127.0.0.1:8080/test.css);" | HTTP_PROXY=http://127.0.0.1:8081 ./bin/cleancss', this.callback); + }, + 'proxies the connection': function () { + assert.isTrue(this.proxied); + }, + 'gives right output': function (error, stdout) { + assert.equal(stdout, 'a{color:red}'); + }, + teardown: function () { + this.proxyServer.close(); + this.server.close(); + } + }) + }) .addBatch({ 'ie7 compatibility': binaryContext('--compatibility ie7 ./test/fixtures/unsupported/selectors-ie7.css', { 'should not transform source': function (error, stdout) { diff --git a/test/protocol-imports-test.js b/test/protocol-imports-test.js index d6ee816c..64e1854d 100644 --- a/test/protocol-imports-test.js +++ b/test/protocol-imports-test.js @@ -1,4 +1,4 @@ -/* jshint unused: false */ +/* jshint unused: false, camelcase: false */ var vows = require('vows'); var assert = require('assert'); @@ -494,34 +494,115 @@ vows.describe('protocol imports').addBatch({ this.server.destroy(); nock.disableNetConnect(); } - }, + } +}).addBatch({ 'of a proxied resource': { topic: function () { + var self = this; + nock.enableNetConnect(); + this.proxied = false; + this.reqMocks = nock('http://assets.127.0.0.1') + .get('/styles.css') + .reply(200, 'a{color:red}'); + + var proxy = httpProxy.createProxyServer(); + this.proxyServer = http.createServer(function (req, res) { + self.proxied = true; + proxy.web(req, res, { target: 'http://' + url.parse(req.url).host }, function () {}); + }); + this.proxyServer.listen(8080, function () { + var options = { + inliner: { + request: { + hostname: '127.0.0.1', + port: 8080 + } + } + }; + + new CleanCSS(options).minify('@import url(http://assets.127.0.0.1/styles.css);', self.callback); + }); + enableDestroy(this.proxyServer); + }, + 'proxies the connection': function () { + assert.isTrue(this.proxied); + }, + 'gets right output': function (errors, minified) { + assert.equal(minified.styles, 'a{color:red}'); + }, + teardown: function () { + assert.isTrue(this.reqMocks.isDone()); + nock.cleanAll(); + this.proxyServer.destroy(); + } + } +}).addBatch({ + 'of a proxied resource via env variables': { + topic: function () { var self = this; + nock.enableNetConnect(); + + this.reqMocks = nock('http://assets.127.0.0.1') + .get('/styles.css') + .reply(200, 'a{color:red}'); + var proxy = httpProxy.createProxyServer(); + this.proxied = false; this.proxyServer = http.createServer(function (req, res) { self.proxied = true; - proxy.web(req, res, { target: 'http://' + url.parse(req.url).host }); + proxy.web(req, res, { target: 'http://' + url.parse(req.url).host }, function (e) { console.log(e); }); + }); + this.proxyServer.listen(8081, function () { + process.env.http_proxy = 'http://127.0.0.1:8081'; + new CleanCSS().minify('@import url(http://assets.127.0.0.1/styles.css);', self.callback); }); - this.proxyServer.listen(8080); enableDestroy(this.proxyServer); + }, + 'proxies the connection': function () { + assert.isTrue(this.proxied); + }, + 'gets right output': function (errors, minified) { + assert.equal(minified.styles, 'a{color:red}'); + }, + teardown: function () { + assert.isTrue(this.reqMocks.isDone()); + nock.cleanAll(); + this.proxyServer.destroy(); + delete process.env.http_proxy; + } + } +}).addBatch({ + 'of a proxied resource via env variables overridden by options': { + topic: function () { + var self = this; + nock.enableNetConnect(); this.reqMocks = nock('http://assets.127.0.0.1') .get('/styles.css') .reply(200, 'a{color:red}'); - var options = { - inliner: { - request: { - hostname: '127.0.0.1', - port: 8080 + var proxy = httpProxy.createProxyServer(); + this.proxied = false; + this.proxyServer = http.createServer(function (req, res) { + self.proxied = true; + proxy.web(req, res, { target: 'http://' + url.parse(req.url).host }, function () {}); + }); + this.proxyServer.listen(8082, function () { + var options = { + inliner: { + request: { + hostname: '127.0.0.1', + port: 8082 + } } - } - }; + }; - new CleanCSS(options).minify('@import url(http://assets.127.0.0.1/styles.css);', this.callback); + process.env.http_proxy = 'http://some-fake-proxy:8082'; + new CleanCSS(options).minify('@import url(http://assets.127.0.0.1/styles.css);', self.callback); + }); + enableDestroy(this.proxyServer); }, 'proxies the connection': function () { assert.isTrue(this.proxied); @@ -533,6 +614,7 @@ vows.describe('protocol imports').addBatch({ assert.isTrue(this.reqMocks.isDone()); nock.cleanAll(); this.proxyServer.destroy(); + delete process.env.http_proxy; } } }).export(module);