Add degraded mode to try and bypass ipv6/gzip issues, refs #4142, refs #4121

main
Jordi Boggiano 9 years ago
parent 417516098e
commit ff84b32097

@ -168,3 +168,25 @@ To enable the swap you can use for example:
/sbin/mkswap /var/swap.1
/sbin/swapon /var/swap.1
```
## Degraded Mode
Due to some intermittent issues on Travis and other systems, we introduced a
degraded network mode which helps Composer finish successfully but disables
a few optimizations. This is enabled automatically when an issue is first
detected.
If you have been pointed to this page, you want to check a few things:
- If you are using ESET antivirus, go in "Advanced Settings" and disable "HTTP-scanner"
under "web access protection"
- If you are using IPv6, try disabling it. If that solves your issues, get in touch
with your ISP or server host, the problem is not at the Packagist level but in the
routing rules between you and Packagist (i.e. the internet at large). The best way to get
these fixed is raise awareness to the network engineers that have the power to fix it.
To disable IPv6 on Linux, try using this command which appends a
rule prefering IPv4 over IPv6 to your config:
`sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf"`
- If none of the above helped, please report the error.

@ -37,6 +37,7 @@ class RemoteFilesystem
private $retryAuthFailure;
private $lastHeaders;
private $storeAuth;
private $degradedMode = false;
/**
* Constructor.
@ -155,6 +156,10 @@ class RemoteFilesystem
if (isset($options['http'])) {
$options['http']['ignore_errors'] = true;
}
if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') {
// access packagist using the resolved IPv4 instead of the hostname to force IPv4 protocol
$fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20);
}
$ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
if ($this->progress) {
@ -186,6 +191,16 @@ class RemoteFilesystem
}
restore_error_handler();
if (isset($e) && !$this->retry) {
if (false !== strpos($e->getMessage(), 'Operation timed out')) {
$this->degradedMode = true;
$this->io->writeError(array(
'<error>'.$e->getMessage().'</error>',
'<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>'
));
return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
}
throw $e;
}
@ -201,36 +216,45 @@ class RemoteFilesystem
$result = false;
}
if ($this->progress && !$this->retry) {
$this->io->overwriteError(" Downloading: <comment>100%</comment>");
}
// decode gzip
if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http') {
$decode = false;
foreach ($http_response_header as $header) {
if (preg_match('{^content-encoding: *gzip *$}i', $header)) {
$decode = true;
continue;
} elseif (preg_match('{^HTTP/}i', $header)) {
$decode = false;
}
}
if ($decode) {
if (PHP_VERSION_ID >= 50400) {
$result = zlib_decode($result);
} else {
// work around issue with gzuncompress & co that do not work with all gzip checksums
$result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
}
try {
if (PHP_VERSION_ID >= 50400) {
$result = zlib_decode($result);
} else {
// work around issue with gzuncompress & co that do not work with all gzip checksums
$result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
}
if (!$result) {
throw new TransportException('Failed to decode zlib stream');
if (!$result) {
throw new TransportException('Failed to decode zlib stream');
}
} catch (\Exception $e) {
$this->degradedMode = true;
$this->io->writeError(array(
'<error>Failed to decode response: '.$e->getMessage().'</error>',
'<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>'
));
return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
}
}
}
if ($this->progress && !$this->retry) {
$this->io->overwriteError(" Downloading: <comment>100%</comment>");
}
// handle copy command if download was successful
if (false !== $result && null !== $fileName) {
if ('' === $result) {
@ -269,6 +293,16 @@ class RemoteFilesystem
$e->setHeaders($http_response_header);
}
if (false !== strpos($e->getMessage(), 'Operation timed out')) {
$this->degradedMode = true;
$this->io->writeError(array(
'<error>'.$e->getMessage().'</error>',
'<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>'
));
return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
}
throw $e;
}
@ -404,8 +438,12 @@ class RemoteFilesystem
}
$options = array_replace_recursive($this->options, $additionalOptions);
$options['http']['protocol_version'] = 1.1;
$headers[] = 'Connection: close';
if (!$this->degradedMode) {
// degraded mode disables HTTP/1.1 which causes issues with some bad
// proxies/software due to the use of chunked encoding
$options['http']['protocol_version'] = 1.1;
$headers[] = 'Connection: close';
}
if ($this->io->hasAuthentication($originUrl)) {
$auth = $this->io->getAuthentication($originUrl);

Loading…
Cancel
Save