Fix output and handling of RFS::copy() and extract redirect code into its own method, refs #4783
parent
a574d5ef76
commit
901e6f1d0e
|
@ -213,8 +213,10 @@ class RemoteFilesystem
|
||||||
unset($additionalOptions['retry-auth-failure']);
|
unset($additionalOptions['retry-auth-failure']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$isRedirect = false;
|
||||||
if (isset($additionalOptions['redirects'])) {
|
if (isset($additionalOptions['redirects'])) {
|
||||||
$this->redirects = $additionalOptions['redirects'];
|
$this->redirects = $additionalOptions['redirects'];
|
||||||
|
$isRedirect = true;
|
||||||
|
|
||||||
unset($additionalOptions['redirects']);
|
unset($additionalOptions['redirects']);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +249,7 @@ class RemoteFilesystem
|
||||||
|
|
||||||
$ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
|
$ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
|
||||||
|
|
||||||
if ($this->progress) {
|
if ($this->progress && !$isRedirect) {
|
||||||
$this->io->writeError(" Downloading: <comment>Connecting...</comment>", false);
|
$this->io->writeError(" Downloading: <comment>Connecting...</comment>", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,47 +297,9 @@ class RemoteFilesystem
|
||||||
$statusCode = $this->findStatusCode($http_response_header);
|
$statusCode = $this->findStatusCode($http_response_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($userlandFollow && $statusCode >= 300 && $statusCode <= 399 && $this->redirects < $this->maxRedirects) {
|
// handle 3xx redirects for php<5.6, 304 Not Modified is excluded
|
||||||
if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
|
if ($userlandFollow && $statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
|
||||||
if (parse_url($locationHeader, PHP_URL_SCHEME)) {
|
$result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
|
||||||
// Absolute URL; e.g. https://example.com/composer
|
|
||||||
$targetUrl = $locationHeader;
|
|
||||||
} elseif (parse_url($locationHeader, PHP_URL_HOST)) {
|
|
||||||
// Scheme relative; e.g. //example.com/foo
|
|
||||||
$targetUrl = $this->scheme.':'.$locationHeader;
|
|
||||||
} elseif ('/' === $locationHeader[0]) {
|
|
||||||
// Absolute path; e.g. /foo
|
|
||||||
$urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
|
|
||||||
|
|
||||||
// Replace path using hostname as an anchor.
|
|
||||||
$targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
|
|
||||||
} else {
|
|
||||||
// Relative path; e.g. foo
|
|
||||||
// This actually differs from PHP which seems to add duplicate slashes.
|
|
||||||
$targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($targetUrl)) {
|
|
||||||
$this->redirects++;
|
|
||||||
|
|
||||||
if ($this->io->isDebug()) {
|
|
||||||
$this->io->writeError(sprintf('Following redirect (%u)', $this->redirects));
|
|
||||||
}
|
|
||||||
|
|
||||||
$additionalOptions['redirects'] = $this->redirects;
|
|
||||||
|
|
||||||
// TODO: Not so sure about preserving origin here...
|
|
||||||
return $this->get($this->originUrl, $targetUrl, $additionalOptions, $this->fileName, $this->progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->retry) {
|
|
||||||
$e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
|
|
||||||
$e->setHeaders($http_response_header);
|
|
||||||
$e->setResponse($result);
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
$result = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail 4xx and 5xx responses and capture the response
|
// fail 4xx and 5xx responses and capture the response
|
||||||
|
@ -350,7 +314,7 @@ class RemoteFilesystem
|
||||||
$result = false;
|
$result = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->progress && !$this->retry) {
|
if ($this->progress && !$this->retry && !$isRedirect) {
|
||||||
$this->io->overwriteError(" Downloading: <comment>100%</comment>");
|
$this->io->overwriteError(" Downloading: <comment>100%</comment>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,7 +351,7 @@ class RemoteFilesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle copy command if download was successful
|
// handle copy command if download was successful
|
||||||
if (false !== $result && null !== $fileName) {
|
if (false !== $result && null !== $fileName && !$isRedirect) {
|
||||||
if ('' === $result) {
|
if ('' === $result) {
|
||||||
throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
|
throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
|
||||||
}
|
}
|
||||||
|
@ -635,6 +599,51 @@ class RemoteFilesystem
|
||||||
return $options;
|
return $options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
|
||||||
|
{
|
||||||
|
if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
|
||||||
|
if (parse_url($locationHeader, PHP_URL_SCHEME)) {
|
||||||
|
// Absolute URL; e.g. https://example.com/composer
|
||||||
|
$targetUrl = $locationHeader;
|
||||||
|
} elseif (parse_url($locationHeader, PHP_URL_HOST)) {
|
||||||
|
// Scheme relative; e.g. //example.com/foo
|
||||||
|
$targetUrl = $this->scheme.':'.$locationHeader;
|
||||||
|
} elseif ('/' === $locationHeader[0]) {
|
||||||
|
// Absolute path; e.g. /foo
|
||||||
|
$urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
|
||||||
|
|
||||||
|
// Replace path using hostname as an anchor.
|
||||||
|
$targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
|
||||||
|
} else {
|
||||||
|
// Relative path; e.g. foo
|
||||||
|
// This actually differs from PHP which seems to add duplicate slashes.
|
||||||
|
$targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($targetUrl)) {
|
||||||
|
$this->redirects++;
|
||||||
|
|
||||||
|
if ($this->io->isDebug()) {
|
||||||
|
$this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
$additionalOptions['redirects'] = $this->redirects;
|
||||||
|
|
||||||
|
return $this->get($this->originUrl, $targetUrl, $additionalOptions, $this->fileName, $this->progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->retry) {
|
||||||
|
$e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
|
||||||
|
$e->setHeaders($http_response_header);
|
||||||
|
$e->setResponse($result);
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $options
|
* @param array $options
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue