Merge branch '4.3' into 4.4
* 4.3: [Console] Add check for Konsole/Yakuake to disable hyperlinks [HttpClient] work around PHP 7.3 bug related to json_encode() [VarDumper] fix dumping the cloner itself Rename the Symfony Mailer service config to avoid conflict with SwitMailer Set default crypto method - Fix #31105 [Form] add missing symfony/service-contracts dependency [HttpClient] Don't throw InvalidArgumentException on bad Location header
This commit is contained in:
commit
7207849037
@ -5,11 +5,12 @@
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
|
||||
<services>
|
||||
<service id="mailer" class="Symfony\Component\Mailer\Mailer">
|
||||
<service id="mailer.mailer" class="Symfony\Component\Mailer\Mailer">
|
||||
<argument type="service" id="mailer.transport" />
|
||||
<argument type="service" id="messenger.default_bus" on-invalid="ignore" />
|
||||
</service>
|
||||
<service id="Symfony\Component\Mailer\MailerInterface" alias="mailer" />
|
||||
<service id="mailer" alias="mailer.mailer" />
|
||||
<service id="Symfony\Component\Mailer\MailerInterface" alias="mailer.mailer" />
|
||||
|
||||
<service id="mailer.transport" class="Symfony\Component\Mailer\Transport\TransportInterface">
|
||||
<factory class="Symfony\Component\Mailer\Transport" method="fromDsn" />
|
||||
|
@ -187,7 +187,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface
|
||||
$unsetCodes = [];
|
||||
|
||||
if (null === $this->handlesHrefGracefully) {
|
||||
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR');
|
||||
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && !getenv('KONSOLE_VERSION');
|
||||
}
|
||||
|
||||
if (null !== $this->foreground) {
|
||||
|
@ -22,7 +22,8 @@
|
||||
"symfony/options-resolver": "~4.3|^5.0",
|
||||
"symfony/polyfill-ctype": "~1.8",
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/property-access": "^3.4|^4.0|^5.0"
|
||||
"symfony/property-access": "^3.4|^4.0|^5.0",
|
||||
"symfony/service-contracts": "~1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/collections": "~1.0",
|
||||
|
@ -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));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -301,7 +301,13 @@ trait HttpClientTrait
|
||||
}
|
||||
|
||||
try {
|
||||
$value = json_encode($value, $flags | (\PHP_VERSION_ID >= 70300 ? JSON_THROW_ON_ERROR : 0), $maxDepth);
|
||||
if (\PHP_VERSION_ID >= 70300) {
|
||||
// Work around https://bugs.php.net/77997
|
||||
json_encode(null);
|
||||
$flags |= JSON_THROW_ON_ERROR;
|
||||
}
|
||||
|
||||
$value = json_encode($value, $flags, $maxDepth);
|
||||
} catch (\JsonException $e) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid value for "json" option: %s.', $e->getMessage()));
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -140,6 +140,9 @@ final class SocketStream extends AbstractStream
|
||||
if ($this->streamContextOptions) {
|
||||
$options = array_merge($options, $this->streamContextOptions);
|
||||
}
|
||||
if ($this->isTLS()) {
|
||||
$options['ssl']['crypto_method'] = $options['ssl']['crypto_method'] ?? STREAM_CRYPTO_METHOD_TLS_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
|
||||
}
|
||||
$streamContext = stream_context_create($options);
|
||||
$this->stream = @stream_socket_client($this->url, $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $streamContext);
|
||||
if (false === $this->stream) {
|
||||
|
@ -84,6 +84,7 @@ abstract class AbstractCloner implements ClonerInterface
|
||||
'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'],
|
||||
'Symfony\Component\VarDumper\Caster\TraceStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'],
|
||||
'Symfony\Component\VarDumper\Caster\FrameStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'],
|
||||
'Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
|
||||
'Symfony\Component\Debug\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'],
|
||||
|
||||
'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'],
|
||||
@ -188,10 +189,7 @@ abstract class AbstractCloner implements ClonerInterface
|
||||
public function addCasters(array $casters)
|
||||
{
|
||||
foreach ($casters as $type => $callback) {
|
||||
$closure = &$this->casters[$type][];
|
||||
$closure = $callback instanceof \Closure ? $callback : static function (...$args) use ($callback, &$closure) {
|
||||
return ($closure = \Closure::fromCallable($callback))(...$args);
|
||||
};
|
||||
$this->casters[$type][] = $callback;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,7 +435,7 @@ class CliDumper extends AbstractDumper
|
||||
}
|
||||
|
||||
if (null === $this->handlesHrefGracefully) {
|
||||
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR');
|
||||
$this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && !getenv('KONSOLE_VERSION');
|
||||
}
|
||||
|
||||
if (isset($attr['ellipsis'], $attr['ellipsis-type'])) {
|
||||
|
@ -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