Handle http 401/403 differently to allow reading warning message
parent
7afd1a9385
commit
174c71de04
|
@ -175,6 +175,24 @@ class RemoteFilesystem
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $headers array of returned headers like from getLastHeaders()
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function findStatusMessage(array $headers)
|
||||||
|
{
|
||||||
|
$value = null;
|
||||||
|
foreach ($headers as $header) {
|
||||||
|
if (preg_match('{^HTTP/\S+ \d+}i', $header)) {
|
||||||
|
// In case of redirects, http_response_headers contains the headers of all responses
|
||||||
|
// so we can not return directly and need to keep iterating
|
||||||
|
$value = $header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get file content or copy action.
|
* Get file content or copy action.
|
||||||
*
|
*
|
||||||
|
@ -299,6 +317,20 @@ class RemoteFilesystem
|
||||||
try {
|
try {
|
||||||
$result = file_get_contents($fileUrl, false, $ctx);
|
$result = file_get_contents($fileUrl, false, $ctx);
|
||||||
|
|
||||||
|
if (!empty($http_response_header[0])) {
|
||||||
|
$statusCode = $this->findStatusCode($http_response_header);
|
||||||
|
if (in_array($statusCode, array(401, 403)) && $this->retryAuthFailure) {
|
||||||
|
$warning = null;
|
||||||
|
if ($this->findHeaderValue($http_response_header, 'content-type') === 'application/json') {
|
||||||
|
$data = json_decode($result, true);
|
||||||
|
if (!empty($data['warning'])) {
|
||||||
|
$warning = $data['warning'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->promptAuthAndRetry($statusCode, $this->findStatusMessage($http_response_header), $warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
|
$contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
|
||||||
if ($contentLength && Platform::strlen($result) < $contentLength) {
|
if ($contentLength && Platform::strlen($result) < $contentLength) {
|
||||||
// alas, this is not possible via the stream callback because STREAM_NOTIFY_COMPLETED is documented, but not implemented anywhere in PHP
|
// alas, this is not possible via the stream callback because STREAM_NOTIFY_COMPLETED is documented, but not implemented anywhere in PHP
|
||||||
|
@ -558,29 +590,6 @@ class RemoteFilesystem
|
||||||
// but you do not send an appropriate certificate
|
// but you do not send an appropriate certificate
|
||||||
throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
|
throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
|
||||||
}
|
}
|
||||||
// intentional fallthrough to the next case as the notificationCode
|
|
||||||
// isn't always consistent and we should inspect the messageCode for 401s
|
|
||||||
|
|
||||||
case STREAM_NOTIFY_AUTH_REQUIRED:
|
|
||||||
if (401 === $messageCode) {
|
|
||||||
// Bail if the caller is going to handle authentication failures itself.
|
|
||||||
if (!$this->retryAuthFailure) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->promptAuthAndRetry($messageCode);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STREAM_NOTIFY_AUTH_RESULT:
|
|
||||||
if (403 === $messageCode) {
|
|
||||||
// Bail if the caller is going to handle authentication failures itself.
|
|
||||||
if (!$this->retryAuthFailure) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->promptAuthAndRetry($messageCode, $message);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STREAM_NOTIFY_FILE_SIZE_IS:
|
case STREAM_NOTIFY_FILE_SIZE_IS:
|
||||||
|
@ -603,7 +612,7 @@ class RemoteFilesystem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function promptAuthAndRetry($httpStatus, $reason = null)
|
protected function promptAuthAndRetry($httpStatus, $reason = null, $warning = null)
|
||||||
{
|
{
|
||||||
if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
|
if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
|
||||||
$message = "\n".'Could not fetch '.$this->fileUrl.', please create a GitHub OAuth token '.($httpStatus === 404 ? 'to access private repos' : 'to go over the API rate limit');
|
$message = "\n".'Could not fetch '.$this->fileUrl.', please create a GitHub OAuth token '.($httpStatus === 404 ? 'to access private repos' : 'to go over the API rate limit');
|
||||||
|
@ -674,6 +683,9 @@ class RemoteFilesystem
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->io->overwriteError('');
|
$this->io->overwriteError('');
|
||||||
|
if ($warning) {
|
||||||
|
$this->io->writeError(' <warning>'.$warning.'</warning>');
|
||||||
|
}
|
||||||
$this->io->writeError(' Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
|
$this->io->writeError(' Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
|
||||||
$username = $this->io->ask(' Username: ');
|
$username = $this->io->ask(' Username: ');
|
||||||
$password = $this->io->askAndHideAnswer(' Password: ');
|
$password = $this->io->askAndHideAnswer(' Password: ');
|
||||||
|
|
Loading…
Reference in New Issue