From e77108d24ee1fd0915129c2d2b312f2f52ccb4b1 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Mon, 8 Apr 2019 20:49:29 +0200 Subject: [PATCH] [HttpClient] Add tests - update code style nits. --- .../HttpClient/CachingHttpClient.php | 2 +- .../Component/HttpClient/CurlHttpClient.php | 6 ++- .../Component/HttpClient/HttpClientTrait.php | 3 +- .../Component/HttpClient/HttpOptions.php | 1 + .../Component/HttpClient/MockHttpClient.php | 2 +- .../Component/HttpClient/NativeHttpClient.php | 12 +----- .../HttpClient/Tests/HttpClientTraitTest.php | 38 +++++++++++++++++++ 7 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CachingHttpClient.php b/src/Symfony/Component/HttpClient/CachingHttpClient.php index 143c5cdc03..3abf3113be 100644 --- a/src/Symfony/Component/HttpClient/CachingHttpClient.php +++ b/src/Symfony/Component/HttpClient/CachingHttpClient.php @@ -71,7 +71,7 @@ class CachingHttpClient implements HttpClientInterface $url = implode('', $url); $options['extra']['no_cache'] = $options['extra']['no_cache'] ?? !$options['buffer']; - if ($options['extra']['no_cache'] || !empty($options['body']) || !\in_array($method, ['GET', 'HEAD', 'OPTIONS'])) { + if (!empty($options['body']) || $options['extra']['no_cache'] || !\in_array($method, ['GET', 'HEAD', 'OPTIONS'])) { return $this->client->request($method, $url, $options); } diff --git a/src/Symfony/Component/HttpClient/CurlHttpClient.php b/src/Symfony/Component/HttpClient/CurlHttpClient.php index a6761e23e8..f59069349e 100644 --- a/src/Symfony/Component/HttpClient/CurlHttpClient.php +++ b/src/Symfony/Component/HttpClient/CurlHttpClient.php @@ -48,6 +48,10 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface */ public function __construct(array $defaultOptions = [], int $maxHostConnections = 6, int $maxPendingPushes = 50) { + if (!\extension_loaded('curl')) { + throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\CurlHttpClient" as the "curl" extension is not installed.'); + } + if ($defaultOptions) { [, $this->defaultOptions] = self::prepareRequest(null, null, $defaultOptions, self::OPTIONS_DEFAULTS); } @@ -109,7 +113,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface $options['headers']['range'] ?? null, ]; - if ('GET' === $method && !$options['body'] && $expectedHeaders === $pushedHeaders) { + if ('GET' === $method && $expectedHeaders === $pushedHeaders && !$options['body']) { $this->logger && $this->logger->debug(sprintf('Connecting request to pushed response: "%s %s"', $method, $url)); // Reinitialize the pushed response with request's options diff --git a/src/Symfony/Component/HttpClient/HttpClientTrait.php b/src/Symfony/Component/HttpClient/HttpClientTrait.php index 3c229bfca9..32e940ac73 100644 --- a/src/Symfony/Component/HttpClient/HttpClientTrait.php +++ b/src/Symfony/Component/HttpClient/HttpClientTrait.php @@ -12,7 +12,6 @@ namespace Symfony\Component\HttpClient; use Symfony\Component\HttpClient\Exception\InvalidArgumentException; -use Symfony\Contracts\HttpClient\HttpClientInterface; /** * Provides the common logic from writing HttpClientInterface implementations. @@ -278,7 +277,7 @@ trait HttpClientTrait $fingerprint[$algo] = 'pin-sha256' === $algo ? (array) $hash : str_replace(':', '', $hash); } } else { - throw new InvalidArgumentException(sprintf('Option "peer_fingerprint" must be string or array, %s given.', \gettype($body))); + throw new InvalidArgumentException(sprintf('Option "peer_fingerprint" must be string or array, %s given.', \gettype($fingerprint))); } return $fingerprint; diff --git a/src/Symfony/Component/HttpClient/HttpOptions.php b/src/Symfony/Component/HttpClient/HttpOptions.php index 85b55f0d08..60df9ac300 100644 --- a/src/Symfony/Component/HttpClient/HttpOptions.php +++ b/src/Symfony/Component/HttpClient/HttpOptions.php @@ -37,6 +37,7 @@ class HttpOptions public function setAuthBasic(string $user, string $password = '') { $this->options['auth_basic'] = $user; + if ('' !== $password) { $this->options['auth_basic'] .= ':'.$password; } diff --git a/src/Symfony/Component/HttpClient/MockHttpClient.php b/src/Symfony/Component/HttpClient/MockHttpClient.php index 41bb20b299..987f04211f 100644 --- a/src/Symfony/Component/HttpClient/MockHttpClient.php +++ b/src/Symfony/Component/HttpClient/MockHttpClient.php @@ -39,7 +39,7 @@ class MockHttpClient implements HttpClientInterface $responseFactory = [$responseFactory]; } - if (null !== $responseFactory && !\is_callable($responseFactory) && !$responseFactory instanceof \Iterator) { + if (!$responseFactory instanceof \Iterator && null !== $responseFactory && !\is_callable($responseFactory)) { $responseFactory = (static function () use ($responseFactory) { yield from $responseFactory; })(); diff --git a/src/Symfony/Component/HttpClient/NativeHttpClient.php b/src/Symfony/Component/HttpClient/NativeHttpClient.php index 03eaeac107..18afa2d13e 100644 --- a/src/Symfony/Component/HttpClient/NativeHttpClient.php +++ b/src/Symfony/Component/HttpClient/NativeHttpClient.php @@ -400,17 +400,9 @@ final class NativeHttpClient implements HttpClientInterface, LoggerAwareInterfac // Matching "no_proxy" should follow the behavior of curl foreach ($noProxy as $rule) { - if ('*' === $rule) { - return stream_context_set_option($context, 'http', 'header', $requestHeaders); - } + $dotRule = '.'.ltrim($rule, '.'); - if ($host === $rule) { - return stream_context_set_option($context, 'http', 'header', $requestHeaders); - } - - $rule = '.'.ltrim($rule, '.'); - - if (substr($host, -\strlen($rule)) === $rule) { + if ('*' === $rule || $host === $rule || substr($host, -\strlen($dotRule)) === $dotRule) { return stream_context_set_option($context, 'http', 'header', $requestHeaders); } } diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php index 5c35bdd320..0a08abec30 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php @@ -215,4 +215,42 @@ class HttpClientTraitTest extends TestCase [, $options] = $this->prepareRequest('POST', 'http://example.com', ['auth_basic' => $arg], HttpClientInterface::OPTIONS_DEFAULTS); $this->assertSame('Basic '.$result, $options['headers']['authorization'][0]); } + + public function provideFingerprints() + { + foreach (['md5', 'sha1', 'sha256'] as $algo) { + $hash = \hash($algo, $algo); + yield [$hash, [$algo => $hash]]; + } + + yield ['AAAA:BBBB:CCCC:DDDD:EEEE:FFFF:GGGG:HHHH:IIII:JJJJ:KKKK', ['pin-sha256' => ['AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKK']]]; + } + + /** + * @dataProvider provideFingerprints + */ + public function testNormalizePeerFingerprint($fingerprint, $expected) + { + self::assertSame($expected, $this->normalizePeerFingerprint($fingerprint)); + } + + /** + * @expectedException \Symfony\Component\HttpClient\Exception\InvalidArgumentException + * @expectedExceptionMessage Cannot auto-detect fingerprint algorithm for "foo". + */ + public function testNormalizePeerFingerprintException() + { + $this->normalizePeerFingerprint('foo'); + } + + /** + * @expectedException \Symfony\Component\HttpClient\Exception\InvalidArgumentException + * @expectedExceptionMessage Option "peer_fingerprint" must be string or array, object given. + */ + public function testNormalizePeerFingerprintTypeException() + { + $fingerprint = new \stdClass(); + + $this->normalizePeerFingerprint($fingerprint); + } }