Browse Source

Add suppor for https_proxy, fixes #3204

Jordi Boggiano 10 years ago
parent
commit
4a6503fe36

+ 40 - 37
src/Composer/Util/StreamContextFactory.php

@@ -43,6 +43,19 @@ final class StreamContextFactory
             $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
         }
 
+        // Override with HTTPS proxy if present and URL is https
+        if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
+            $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
+        }
+
+        // Remove proxy if URL matches no_proxy directive
+        if (!empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
+            $pattern = new NoProxyPattern($_SERVER['no_proxy']);
+            if ($pattern->test($url)) {
+                unset($proxy);
+            }
+        }
+
         if (!empty($proxy)) {
             $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
             $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
@@ -64,48 +77,38 @@ final class StreamContextFactory
 
             $options['http']['proxy'] = $proxyURL;
 
-            // Handle no_proxy directive
-            if (!empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
-                $pattern = new NoProxyPattern($_SERVER['no_proxy']);
-                if ($pattern->test($url)) {
-                    unset($options['http']['proxy']);
-                }
+            // enabled request_fulluri unless it is explicitly disabled
+            switch (parse_url($url, PHP_URL_SCHEME)) {
+                case 'http': // default request_fulluri to true
+                    $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
+                    if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
+                        $options['http']['request_fulluri'] = true;
+                    }
+                    break;
+                case 'https': // default request_fulluri to true
+                    $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
+                    if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
+                        $options['http']['request_fulluri'] = true;
+                    }
+                    break;
             }
 
-            // add request_fulluri and authentication if we still have a proxy to connect to
-            if (!empty($options['http']['proxy'])) {
-                // enabled request_fulluri unless it is explicitly disabled
-                switch (parse_url($url, PHP_URL_SCHEME)) {
-                    case 'http': // default request_fulluri to true
-                        $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
-                        if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
-                            $options['http']['request_fulluri'] = true;
-                        }
-                        break;
-                    case 'https': // default request_fulluri to true
-                        $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
-                        if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
-                            $options['http']['request_fulluri'] = true;
-                        }
-                        break;
+            // handle proxy auth if present
+            if (isset($proxy['user'])) {
+                $auth = urldecode($proxy['user']);
+                if (isset($proxy['pass'])) {
+                    $auth .= ':' . urldecode($proxy['pass']);
                 }
+                $auth = base64_encode($auth);
 
-                if (isset($proxy['user'])) {
-                    $auth = urldecode($proxy['user']);
-                    if (isset($proxy['pass'])) {
-                        $auth .= ':' . urldecode($proxy['pass']);
-                    }
-                    $auth = base64_encode($auth);
-
-                    // Preserve headers if already set in default options
-                    if (isset($defaultOptions['http']['header'])) {
-                        if (is_string($defaultOptions['http']['header'])) {
-                            $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
-                        }
-                        $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
-                    } else {
-                        $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
+                // Preserve headers if already set in default options
+                if (isset($defaultOptions['http']['header'])) {
+                    if (is_string($defaultOptions['http']['header'])) {
+                        $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
                     }
+                    $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
+                } else {
+                    $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
                 }
             }
         }

+ 22 - 1
tests/Composer/Test/Util/StreamContextFactoryTest.php

@@ -20,6 +20,8 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase
     {
         unset($_SERVER['HTTP_PROXY']);
         unset($_SERVER['http_proxy']);
+        unset($_SERVER['HTTPS_PROXY']);
+        unset($_SERVER['https_proxy']);
         unset($_SERVER['no_proxy']);
     }
 
@@ -27,6 +29,8 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase
     {
         unset($_SERVER['HTTP_PROXY']);
         unset($_SERVER['http_proxy']);
+        unset($_SERVER['HTTPS_PROXY']);
+        unset($_SERVER['https_proxy']);
         unset($_SERVER['no_proxy']);
     }
 
@@ -126,7 +130,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase
     {
         $_SERVER['http_proxy'] = 'http://username:password@proxyserver.net';
 
-        $context = StreamContextFactory::getContext('http://example.org', array('http' => array('method' => 'GET')));
+        $context = StreamContextFactory::getContext('https://example.org', array('http' => array('method' => 'GET')));
         $options = stream_context_get_options($context);
 
         $this->assertEquals(array('http' => array(
@@ -139,6 +143,23 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase
         )), $options);
     }
 
+    public function testHttpsProxyOverride()
+    {
+        $_SERVER['http_proxy'] = 'http://username:password@proxyserver.net';
+        $_SERVER['http_proxy'] = 'https://woopproxy.net';
+
+        $context = StreamContextFactory::getContext('https://example.org', array('http' => array('method' => 'GET')));
+        $options = stream_context_get_options($context);
+
+        $this->assertEquals(array('http' => array(
+            'proxy' => 'ssl://woopproxy.net:443',
+            'request_fulluri' => true,
+            'method' => 'GET',
+            'max_redirects' => 20,
+            'follow_location' => 1,
+        )), $options);
+    }
+
     /**
      * @dataProvider dataSSLProxy
      */