1
0
Fork 0

Deduplicate findHeaderValue code

pull/8295/head
Jordi Boggiano 2019-08-02 21:54:41 +02:00
parent 63da7c6b2d
commit bfee701f9b
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC
4 changed files with 33 additions and 45 deletions

View File

@ -19,7 +19,6 @@ use Composer\Cache;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Util\GitHub; use Composer\Util\GitHub;
use Composer\Util\Http\Response; use Composer\Util\Http\Response;
use Composer\Util\RemoteFilesystem;
/** /**
* @author Jordi Boggiano <j.boggiano@seld.be> * @author Jordi Boggiano <j.boggiano@seld.be>
@ -346,10 +345,10 @@ class GitHubDriver extends VcsDriver
$scopesIssued = array(); $scopesIssued = array();
$scopesNeeded = array(); $scopesNeeded = array();
if ($headers = $e->getHeaders()) { if ($headers = $e->getHeaders()) {
if ($scopes = RemoteFilesystem::findHeaderValue($headers, 'X-OAuth-Scopes')) { if ($scopes = Response::findHeaderValue($headers, 'X-OAuth-Scopes')) {
$scopesIssued = explode(' ', $scopes); $scopesIssued = explode(' ', $scopes);
} }
if ($scopes = RemoteFilesystem::findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) { if ($scopes = Response::findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
$scopesNeeded = explode(' ', $scopes); $scopesNeeded = explode(' ', $scopes);
} }
} }

View File

@ -16,7 +16,6 @@ use Composer\Config;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Downloader\TransportException; use Composer\Downloader\TransportException;
use Composer\CaBundle\CaBundle; use Composer\CaBundle\CaBundle;
use Composer\Util\RemoteFilesystem;
use Composer\Util\StreamContextFactory; use Composer\Util\StreamContextFactory;
use Composer\Util\AuthHelper; use Composer\Util\AuthHelper;
use Composer\Util\Url; use Composer\Util\Url;

View File

@ -61,20 +61,7 @@ class Response
public function getHeader($name) public function getHeader($name)
{ {
$value = null; return self::findHeaderValue($this->headers, $name);
foreach ($this->headers as $header) {
if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
$value = $match[1];
} elseif (preg_match('{^HTTP/}i', $header)) {
// TODO ideally redirects would be handled in CurlDownloader/RemoteFilesystem and this becomes unnecessary
//
// In case of redirects, headers contains the headers of all responses
// so we reset the flag when a new response is being parsed as we are only interested in the last response
$value = null;
}
}
return $value;
} }
public function getBody() public function getBody()
@ -91,4 +78,27 @@ class Response
{ {
$this->request = $this->code = $this->headers = $this->body = null; $this->request = $this->code = $this->headers = $this->body = null;
} }
/**
* @param array $headers array of returned headers like from getLastHeaders()
* @param string $name header name (case insensitive)
* @return string|null
*/
public static function findHeaderValue(array $headers, $name)
{
$value = null;
foreach ($headers as $header) {
if (preg_match('{^'.preg_quote($name).':\s*(.+?)\s*$}i', $header, $match)) {
$value = $match[1];
} elseif (preg_match('{^HTTP/}i', $header)) {
// TODO ideally redirects would be handled in CurlDownloader/RemoteFilesystem and this becomes unnecessary
//
// In case of redirects, http_response_headers contains the headers of all responses
// so we reset the flag when a new response is being parsed as we are only interested in the last response
$value = null;
}
}
return $value;
}
} }

View File

@ -17,6 +17,7 @@ use Composer\IO\IOInterface;
use Composer\Downloader\TransportException; use Composer\Downloader\TransportException;
use Composer\CaBundle\CaBundle; use Composer\CaBundle\CaBundle;
use Composer\Util\HttpDownloader; use Composer\Util\HttpDownloader;
use Composer\Util\Response;
/** /**
* @author François Pluchino <francois.pluchino@opendisplay.com> * @author François Pluchino <francois.pluchino@opendisplay.com>
@ -143,27 +144,6 @@ class RemoteFilesystem
return $this->lastHeaders; return $this->lastHeaders;
} }
/**
* @param array $headers array of returned headers like from getLastHeaders()
* @param string $name header name (case insensitive)
* @return string|null
*/
public static function findHeaderValue(array $headers, $name)
{
$value = null;
foreach ($headers as $header) {
if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
$value = $match[1];
} elseif (preg_match('{^HTTP/}i', $header)) {
// In case of redirects, http_response_headers contains the headers of all responses
// so we reset the flag when a new response is being parsed as we are only interested in the last response
$value = null;
}
}
return $value;
}
/** /**
* @param array $headers array of returned headers like from getLastHeaders() * @param array $headers array of returned headers like from getLastHeaders()
* @return int|null * @return int|null
@ -294,7 +274,7 @@ class RemoteFilesystem
if (!empty($http_response_header[0])) { if (!empty($http_response_header[0])) {
$statusCode = $this->findStatusCode($http_response_header); $statusCode = $this->findStatusCode($http_response_header);
if ($statusCode >= 400 && $this->findHeaderValue($http_response_header, 'content-type') === 'application/json') { if ($statusCode >= 400 && Response::findHeaderValue($http_response_header, 'content-type') === 'application/json') {
HttpDownloader::outputWarnings($this->io, $originUrl, json_decode($result, true)); HttpDownloader::outputWarnings($this->io, $originUrl, json_decode($result, true));
} }
@ -303,7 +283,7 @@ class RemoteFilesystem
} }
} }
$contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null; $contentLength = !empty($http_response_header[0]) ? Response::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
$e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength); $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
@ -360,8 +340,8 @@ class RemoteFilesystem
$locationHeader = null; $locationHeader = null;
if (!empty($http_response_header[0])) { if (!empty($http_response_header[0])) {
$statusCode = $this->findStatusCode($http_response_header); $statusCode = $this->findStatusCode($http_response_header);
$contentType = $this->findHeaderValue($http_response_header, 'content-type'); $contentType = Response::findHeaderValue($http_response_header, 'content-type');
$locationHeader = $this->findHeaderValue($http_response_header, 'location'); $locationHeader = Response::findHeaderValue($http_response_header, 'location');
} }
// check for bitbucket login page asking to authenticate // check for bitbucket login page asking to authenticate
@ -417,7 +397,7 @@ class RemoteFilesystem
// decode gzip // decode gzip
if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) { if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
$contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding'); $contentEncoding = Response::findHeaderValue($http_response_header, 'content-encoding');
$decode = $contentEncoding && 'gzip' === strtolower($contentEncoding); $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
if ($decode) { if ($decode) {
@ -700,7 +680,7 @@ class RemoteFilesystem
private function handleRedirect(array $http_response_header, array $additionalOptions, $result) private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
{ {
if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) { if ($locationHeader = Response::findHeaderValue($http_response_header, 'location')) {
if (parse_url($locationHeader, PHP_URL_SCHEME)) { if (parse_url($locationHeader, PHP_URL_SCHEME)) {
// Absolute URL; e.g. https://example.com/composer // Absolute URL; e.g. https://example.com/composer
$targetUrl = $locationHeader; $targetUrl = $locationHeader;