diff --git a/doc/03-cli.md b/doc/03-cli.md index e4f7f9083..f179e4720 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -423,6 +423,12 @@ If you use a proxy but it does not support the request_fulluri flag, then you should set this env var to `false` or `0` to prevent composer from setting the request_fulluri option. +### HTTPS_PROXY_REQUEST_FULLURI + +If you use a proxy but it does not support the request_fulluri flag for HTTPS +requests, then you should set this env var to `false` or `0` to prevent composer +from setting the request_fulluri option. + ### COMPOSER_HOME The `COMPOSER_HOME` var allows you to change the composer home directory. This diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 07600e0e5..1c0cf3f90 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -52,10 +52,12 @@ EOT $output->write('Checking http connectivity: '); $this->outputResult($output, $this->checkHttp()); - $opts = stream_context_get_options(StreamContextFactory::getContext()); + $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org')); if (!empty($opts['http']['proxy'])) { $output->write('Checking HTTP proxy: '); $this->outputResult($output, $this->checkHttpProxy()); + $output->write('Checking HTTP proxy support for request_fulluri: '); + $this->outputResult($output, $this->checkHttpProxyFullUriRequestParam()); $output->write('Checking HTTPS proxy support for request_fulluri: '); $this->outputResult($output, $this->checkHttpsProxyFullUriRequestParam()); } @@ -142,7 +144,32 @@ EOT } /** - * Due to various proxy servers configurations, some servers cant handle non-standard HTTP "http_proxy_request_fulluri" parameter, + * Due to various proxy servers configurations, some servers can't handle non-standard HTTP "http_proxy_request_fulluri" parameter, + * and will return error 500/501 (as not implemented), see discussion @ https://github.com/composer/composer/pull/1825. + * This method will test, if you need to disable this parameter via setting extra environment variable in your system. + * + * @return bool|string + */ + private function checkHttpProxyFullUriRequestParam() + { + $url = 'http://packagist.org/packages.json'; + try { + $this->rfs->getContents('packagist.org', $url, false); + } catch (TransportException $e) { + try { + $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false))); + } catch (TransportException $e) { + return 'Unable to assert the situation, maybe packagist.org is down ('.$e->getMessage().')'; + } + + return 'It seems there is a problem with your proxy server, try setting the "HTTP_PROXY_REQUEST_FULLURI" and "HTTPS_PROXY_REQUEST_FULLURI" environment variables to "false"'; + } + + return true; + } + + /** + * Due to various proxy servers configurations, some servers can't handle non-standard HTTP "http_proxy_request_fulluri" parameter, * and will return error 500/501 (as not implemented), see discussion @ https://github.com/composer/composer/pull/1825. * This method will test, if you need to disable this parameter via setting extra environment variable in your system. * @@ -150,21 +177,21 @@ EOT */ private function checkHttpsProxyFullUriRequestParam() { - $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0 '; + if (!extension_loaded('openssl')) { + return 'You need the openssl extension installed for this check'; + } + + $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0'; try { $rfcResult = $this->rfs->getContents('api.github.com', $url, false); } catch (TransportException $e) { - if (!extension_loaded('openssl')) { - return 'You need the openssl extension installed for this check'; - } - try { $this->rfs->getContents('api.github.com', $url, false, array('http' => array('request_fulluri' => false))); } catch (TransportException $e) { return 'Unable to assert the situation, maybe github is down ('.$e->getMessage().')'; } - return 'It seems there is a problem with your proxy server, try setting the "HTTP_PROXY_REQUEST_FULLURI" environment variable to "false"'; + return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"'; } return true; diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 55e1eef4b..2a9021324 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -251,7 +251,7 @@ class InstallationManager ) ); - $context = StreamContextFactory::getContext($opts); + $context = StreamContextFactory::getContext($url, $opts); @file_get_contents($url, false, $context); } @@ -275,7 +275,7 @@ class InstallationManager ) ); - $context = StreamContextFactory::getContext($opts); + $context = StreamContextFactory::getContext($repoUrl, $opts); @file_get_contents($repoUrl, false, $context); } diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 8b4c4a0dc..05f99abde 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -104,7 +104,7 @@ class RemoteFilesystem $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token']; unset($options['github-token']); } - $ctx = StreamContextFactory::getContext($options, array('notification' => array($this, 'callbackGet'))); + $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet'))); if ($this->progress) { $this->io->write(" Downloading: connection...", false); diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index d89b115f6..26590ada6 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -23,12 +23,13 @@ final class StreamContextFactory /** * Creates a context supporting HTTP proxies * + * @param string $url URL the context is to be used for * @param array $defaultOptions Options to merge with the default * @param array $defaultParams Parameters to specify on the context * @return resource Default context * @throws \RuntimeException if https proxy required and OpenSSL uninstalled */ - public static function getContext(array $defaultOptions = array(), array $defaultParams = array()) + public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array()) { $options = array('http' => array( // specify defaults again to try and work better with curlwrappers enabled @@ -64,9 +65,19 @@ final class StreamContextFactory $options['http']['proxy'] = $proxyURL; // enabled request_fulluri unless it is explicitly disabled - $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI'); - if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) { - $options['http']['request_fulluri'] = true; + 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; } if (isset($proxy['user'])) { diff --git a/tests/Composer/Test/Util/StreamContextFactoryTest.php b/tests/Composer/Test/Util/StreamContextFactoryTest.php index 86ee8515d..c91c1959f 100644 --- a/tests/Composer/Test/Util/StreamContextFactoryTest.php +++ b/tests/Composer/Test/Util/StreamContextFactoryTest.php @@ -33,7 +33,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase */ public function testGetContext($expectedOptions, $defaultOptions, $expectedParams, $defaultParams) { - $context = StreamContextFactory::getContext($defaultOptions, $defaultParams); + $context = StreamContextFactory::getContext('http://example.org', $defaultOptions, $defaultParams); $options = stream_context_get_options($context); $params = stream_context_get_params($context); @@ -60,7 +60,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase $_SERVER['http_proxy'] = 'http://username:password@proxyserver.net:3128/'; $_SERVER['HTTP_PROXY'] = 'http://proxyserver/'; - $context = StreamContextFactory::getContext(array('http' => array('method' => 'GET'))); + $context = StreamContextFactory::getContext('http://example.org', array('http' => array('method' => 'GET'))); $options = stream_context_get_options($context); $this->assertEquals(array('http' => array( @@ -77,7 +77,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase { $_SERVER['http_proxy'] = 'http://username:password@proxyserver.net:3128/'; - $context = StreamContextFactory::getContext(array('http' => array('method' => 'GET', 'header' => array("X-Foo: bar"), 'request_fulluri' => false))); + $context = StreamContextFactory::getContext('http://example.org', array('http' => array('method' => 'GET', 'header' => array("X-Foo: bar"), 'request_fulluri' => false))); $options = stream_context_get_options($context); $this->assertEquals(array('http' => array( @@ -94,7 +94,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase { $_SERVER['http_proxy'] = 'http://username:password@proxyserver.net'; - $context = StreamContextFactory::getContext(array('http' => array('method' => 'GET'))); + $context = StreamContextFactory::getContext('http://example.org', array('http' => array('method' => 'GET'))); $options = stream_context_get_options($context); $this->assertEquals(array('http' => array( @@ -115,7 +115,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase $_SERVER['http_proxy'] = $proxy; if (extension_loaded('openssl')) { - $context = StreamContextFactory::getContext(); + $context = StreamContextFactory::getContext('http://example.org'); $options = stream_context_get_options($context); $this->assertEquals(array('http' => array( @@ -161,7 +161,7 @@ class StreamContextFactoryTest extends \PHPUnit_Framework_TestCase ) ) ); - $context = StreamContextFactory::getContext($options); + $context = StreamContextFactory::getContext('http://example.org', $options); $ctxoptions = stream_context_get_options($context); $this->assertEquals(join("\n", $ctxoptions['http']['header']), join("\n", $expectedOptions['http']['header'])); }