[HttpClient] Don't throw InvalidArgumentException on bad Location header
This commit is contained in:
parent
f6a6fb6834
commit
4acca42330
@ -14,6 +14,7 @@ namespace Symfony\Component\HttpClient;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||
use Symfony\Component\HttpClient\Internal\CurlClientState;
|
||||
use Symfony\Component\HttpClient\Internal\PushedResponse;
|
||||
@ -392,14 +393,20 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface
|
||||
}
|
||||
|
||||
return static function ($ch, string $location) use ($redirectHeaders) {
|
||||
if ($redirectHeaders && $host = parse_url($location, PHP_URL_HOST)) {
|
||||
try {
|
||||
$location = self::parseUrl($location);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($redirectHeaders && $host = parse_url('http:'.$location['authority'], PHP_URL_HOST)) {
|
||||
$requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth'];
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
|
||||
}
|
||||
|
||||
$url = self::parseUrl(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
|
||||
|
||||
return implode('', self::resolveUrl(self::parseUrl($location), $url));
|
||||
return implode('', self::resolveUrl($location, $url));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\HttpClient;
|
||||
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||
use Symfony\Component\HttpClient\Internal\NativeClientState;
|
||||
use Symfony\Component\HttpClient\Response\NativeResponse;
|
||||
@ -352,7 +353,15 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac
|
||||
return null;
|
||||
}
|
||||
|
||||
$url = self::resolveUrl(self::parseUrl($location), $info['url']);
|
||||
try {
|
||||
$url = self::parseUrl($location);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$info['redirect_url'] = null;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$url = self::resolveUrl($url, $info['url']);
|
||||
$info['redirect_url'] = implode('', $url);
|
||||
|
||||
if ($info['redirect_count'] >= $maxRedirects) {
|
||||
|
@ -310,7 +310,11 @@ final class CurlResponse implements ResponseInterface
|
||||
$info['redirect_url'] = null;
|
||||
|
||||
if (300 <= $statusCode && $statusCode < 400 && null !== $location) {
|
||||
$info['redirect_url'] = $resolveRedirect($ch, $location);
|
||||
if (null === $info['redirect_url'] = $resolveRedirect($ch, $location)) {
|
||||
$options['max_redirects'] = curl_getinfo($ch, CURLINFO_REDIRECT_COUNT);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
|
||||
curl_setopt($ch, CURLOPT_MAXREDIRS, $options['max_redirects']);
|
||||
} else {
|
||||
$url = parse_url($location ?? ':');
|
||||
|
||||
if (isset($url['host']) && null !== $ip = $multi->dnsCache->hostnames[$url['host'] = strtolower($url['host'])] ?? null) {
|
||||
@ -320,6 +324,7 @@ final class CurlResponse implements ResponseInterface
|
||||
$multi->dnsCache->removals["-{$url['host']}:$port"] = "-{$url['host']}:$port";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$location = null;
|
||||
|
||||
|
@ -55,6 +55,10 @@ switch ($vars['REQUEST_URI']) {
|
||||
header('Location: http://foo.example.', true, 301);
|
||||
break;
|
||||
|
||||
case '/301/invalid':
|
||||
header('Location: //?foo=bar', true, 301);
|
||||
break;
|
||||
|
||||
case '/302':
|
||||
if (!isset($vars['HTTP_AUTHORIZATION'])) {
|
||||
header('Location: http://localhost:8057/', true, 302);
|
||||
|
@ -259,6 +259,20 @@ abstract class HttpClientTestCase extends TestCase
|
||||
$this->assertSame($expected, $filteredHeaders);
|
||||
}
|
||||
|
||||
public function testInvalidRedirect()
|
||||
{
|
||||
$client = $this->getHttpClient(__FUNCTION__);
|
||||
$response = $client->request('GET', 'http://localhost:8057/301/invalid');
|
||||
|
||||
$this->assertSame(301, $response->getStatusCode());
|
||||
$this->assertSame(['//?foo=bar'], $response->getHeaders(false)['location']);
|
||||
$this->assertSame(0, $response->getInfo('redirect_count'));
|
||||
$this->assertNull($response->getInfo('redirect_url'));
|
||||
|
||||
$this->expectException(RedirectionExceptionInterface::class);
|
||||
$response->getHeaders();
|
||||
}
|
||||
|
||||
public function testRelativeRedirects()
|
||||
{
|
||||
$client = $this->getHttpClient(__FUNCTION__);
|
||||
|
Reference in New Issue
Block a user