Adds inferring proxy settings from environment variables.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 16 Aug 2015 11:17:55 +0000 (12:17 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 16 Aug 2015 11:21:55 +0000 (12:21 +0100)
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
```

History.md
lib/clean.js
test/binary-test.js
test/protocol-imports-test.js

index 4a20e7f..cf383db 100644 (file)
@@ -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.
index aa47cd1..1ef29cb 100644 (file)
@@ -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: {},
index d3f345a..b60c9ac 100644 (file)
@@ -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) {
index d6ee816..64e1854 100644 (file)
@@ -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);