[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\LoggerAwareInterface;
|
||||||
use Psr\Log\LoggerAwareTrait;
|
use Psr\Log\LoggerAwareTrait;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
||||||
use Symfony\Component\HttpClient\Exception\TransportException;
|
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||||
use Symfony\Component\HttpClient\Internal\CurlClientState;
|
use Symfony\Component\HttpClient\Internal\CurlClientState;
|
||||||
use Symfony\Component\HttpClient\Internal\PushedResponse;
|
use Symfony\Component\HttpClient\Internal\PushedResponse;
|
||||||
@ -392,14 +393,20 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
return static function ($ch, string $location) use ($redirectHeaders) {
|
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'];
|
$requestHeaders = $redirectHeaders['host'] === $host ? $redirectHeaders['with_auth'] : $redirectHeaders['no_auth'];
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = self::parseUrl(curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
|
$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\LoggerAwareInterface;
|
||||||
use Psr\Log\LoggerAwareTrait;
|
use Psr\Log\LoggerAwareTrait;
|
||||||
|
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
|
||||||
use Symfony\Component\HttpClient\Exception\TransportException;
|
use Symfony\Component\HttpClient\Exception\TransportException;
|
||||||
use Symfony\Component\HttpClient\Internal\NativeClientState;
|
use Symfony\Component\HttpClient\Internal\NativeClientState;
|
||||||
use Symfony\Component\HttpClient\Response\NativeResponse;
|
use Symfony\Component\HttpClient\Response\NativeResponse;
|
||||||
@ -352,7 +353,15 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac
|
|||||||
return null;
|
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);
|
$info['redirect_url'] = implode('', $url);
|
||||||
|
|
||||||
if ($info['redirect_count'] >= $maxRedirects) {
|
if ($info['redirect_count'] >= $maxRedirects) {
|
||||||
|
@ -310,7 +310,11 @@ final class CurlResponse implements ResponseInterface
|
|||||||
$info['redirect_url'] = null;
|
$info['redirect_url'] = null;
|
||||||
|
|
||||||
if (300 <= $statusCode && $statusCode < 400 && null !== $location) {
|
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 ?? ':');
|
$url = parse_url($location ?? ':');
|
||||||
|
|
||||||
if (isset($url['host']) && null !== $ip = $multi->dnsCache->hostnames[$url['host'] = strtolower($url['host'])] ?? null) {
|
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";
|
$multi->dnsCache->removals["-{$url['host']}:$port"] = "-{$url['host']}:$port";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$location = null;
|
$location = null;
|
||||||
|
|
||||||
|
@ -55,6 +55,10 @@ switch ($vars['REQUEST_URI']) {
|
|||||||
header('Location: http://foo.example.', true, 301);
|
header('Location: http://foo.example.', true, 301);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '/301/invalid':
|
||||||
|
header('Location: //?foo=bar', true, 301);
|
||||||
|
break;
|
||||||
|
|
||||||
case '/302':
|
case '/302':
|
||||||
if (!isset($vars['HTTP_AUTHORIZATION'])) {
|
if (!isset($vars['HTTP_AUTHORIZATION'])) {
|
||||||
header('Location: http://localhost:8057/', true, 302);
|
header('Location: http://localhost:8057/', true, 302);
|
||||||
|
@ -259,6 +259,20 @@ abstract class HttpClientTestCase extends TestCase
|
|||||||
$this->assertSame($expected, $filteredHeaders);
|
$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()
|
public function testRelativeRedirects()
|
||||||
{
|
{
|
||||||
$client = $this->getHttpClient(__FUNCTION__);
|
$client = $this->getHttpClient(__FUNCTION__);
|
||||||
|
Reference in New Issue
Block a user