Skip to content

Commit 3fc1acc

Browse files
[HttpClient] Add HttpClientInterface::withOptions()
1 parent c6f5bbe commit 3fc1acc

11 files changed

+130
-33
lines changed

AsyncDecoratorTrait.php

+11
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,15 @@ public function stream($responses, float $timeout = null): ResponseStreamInterfa
5151

5252
return new ResponseStream(AsyncResponse::stream($responses, $timeout, static::class));
5353
}
54+
55+
/**
56+
* {@inheritdoc}
57+
*/
58+
public function withOptions(array $options): self
59+
{
60+
$clone = clone $this;
61+
$clone->client = $this->client->withOptions($options);
62+
63+
return $clone;
64+
}
5465
}

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.3
5+
---
6+
7+
* Implement `HttpClientInterface::withOptions()` from `symfony/contracts` v2.4
8+
49
5.2.0
510
-----
611

CurlHttpClient.php

+3-25
Original file line numberDiff line numberDiff line change
@@ -341,30 +341,8 @@ public function stream($responses, float $timeout = null): ResponseStreamInterfa
341341

342342
public function reset()
343343
{
344-
if ($this->logger) {
345-
foreach ($this->multi->pushedResponses as $url => $response) {
346-
$this->logger->debug(sprintf('Unused pushed response: "%s"', $url));
347-
}
348-
}
349-
350-
$this->multi->pushedResponses = [];
351-
$this->multi->dnsCache->evictions = $this->multi->dnsCache->evictions ?: $this->multi->dnsCache->removals;
352-
$this->multi->dnsCache->removals = $this->multi->dnsCache->hostnames = [];
353-
354-
if (\is_resource($this->multi->handle) || $this->multi->handle instanceof \CurlMultiHandle) {
355-
if (\defined('CURLMOPT_PUSHFUNCTION')) {
356-
curl_multi_setopt($this->multi->handle, \CURLMOPT_PUSHFUNCTION, null);
357-
}
358-
359-
$active = 0;
360-
while (\CURLM_CALL_MULTI_PERFORM === curl_multi_exec($this->multi->handle, $active));
361-
}
362-
363-
foreach ($this->multi->openHandles as [$ch]) {
364-
if (\is_resource($ch) || $ch instanceof \CurlHandle) {
365-
curl_setopt($ch, \CURLOPT_VERBOSE, false);
366-
}
367-
}
344+
$this->multi->logger = $this->logger;
345+
$this->multi->reset();
368346
}
369347

370348
public function __sleep()
@@ -379,7 +357,7 @@ public function __wakeup()
379357

380358
public function __destruct()
381359
{
382-
$this->reset();
360+
$this->multi->logger = $this->logger;
383361
}
384362

385363
private function handlePush($parent, $pushed, array $requestHeaders, int $maxPendingPushes): int

EventSourceHttpClient.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
*/
2727
final class EventSourceHttpClient implements HttpClientInterface
2828
{
29-
use AsyncDecoratorTrait;
30-
use HttpClientTrait;
29+
use AsyncDecoratorTrait, HttpClientTrait {
30+
AsyncDecoratorTrait::withOptions insteadof HttpClientTrait;
31+
}
3132

3233
private $reconnectionTime;
3334

HttpClientTrait.php

+12-1
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,25 @@
1717
/**
1818
* Provides the common logic from writing HttpClientInterface implementations.
1919
*
20-
* All methods are static to prevent implementers from creating memory leaks via circular references.
20+
* All private methods are static to prevent implementers from creating memory leaks via circular references.
2121
*
2222
* @author Nicolas Grekas <[email protected]>
2323
*/
2424
trait HttpClientTrait
2525
{
2626
private static $CHUNK_SIZE = 16372;
2727

28+
/**
29+
* {@inheritdoc}
30+
*/
31+
public function withOptions(array $options): self
32+
{
33+
$clone = clone $this;
34+
$clone->defaultOptions = self::mergeDefaultOptions($options, $this->defaultOptions);
35+
36+
return $clone;
37+
}
38+
2839
/**
2940
* Validates and normalizes method, URL and options, and merges them with defaults.
3041
*

Internal/CurlClientState.php

+47
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\HttpClient\Internal;
1313

14+
use Psr\Log\LoggerInterface;
15+
1416
/**
1517
* Internal representation of the cURL client's state.
1618
*
@@ -29,10 +31,55 @@ final class CurlClientState extends ClientState
2931
/** @var float[] */
3032
public $pauseExpiries = [];
3133
public $execCounter = \PHP_INT_MIN;
34+
/** @var LoggerInterface|null */
35+
public $logger;
3236

3337
public function __construct()
3438
{
3539
$this->handle = curl_multi_init();
3640
$this->dnsCache = new DnsCache();
3741
}
42+
43+
public function reset()
44+
{
45+
if ($this->logger) {
46+
foreach ($this->pushedResponses as $url => $response) {
47+
$this->logger->debug(sprintf('Unused pushed response: "%s"', $url));
48+
}
49+
}
50+
51+
$this->pushedResponses = [];
52+
$this->dnsCache->evictions = $this->dnsCache->evictions ?: $this->dnsCache->removals;
53+
$this->dnsCache->removals = $this->dnsCache->hostnames = [];
54+
55+
if (\is_resource($this->handle) || $this->handle instanceof \CurlMultiHandle) {
56+
if (\defined('CURLMOPT_PUSHFUNCTION')) {
57+
curl_multi_setopt($this->handle, \CURLMOPT_PUSHFUNCTION, null);
58+
}
59+
60+
$active = 0;
61+
while (\CURLM_CALL_MULTI_PERFORM === curl_multi_exec($this->handle, $active));
62+
}
63+
64+
foreach ($this->openHandles as [$ch]) {
65+
if (\is_resource($ch) || $ch instanceof \CurlHandle) {
66+
curl_setopt($ch, \CURLOPT_VERBOSE, false);
67+
}
68+
}
69+
}
70+
71+
public function __sleep()
72+
{
73+
throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
74+
}
75+
76+
public function __wakeup()
77+
{
78+
throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
79+
}
80+
81+
public function __destruct()
82+
{
83+
$this->reset();
84+
}
3885
}

MockHttpClient.php

+14-3
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ class MockHttpClient implements HttpClientInterface
2828
use HttpClientTrait;
2929

3030
private $responseFactory;
31-
private $baseUri;
3231
private $requestsCount = 0;
32+
private $defaultOptions = [];
3333

3434
/**
3535
* @param callable|callable[]|ResponseInterface|ResponseInterface[]|iterable|null $responseFactory
@@ -47,15 +47,15 @@ public function __construct($responseFactory = null, string $baseUri = null)
4747
}
4848

4949
$this->responseFactory = $responseFactory;
50-
$this->baseUri = $baseUri;
50+
$this->defaultOptions['base_uri'] = $baseUri;
5151
}
5252

5353
/**
5454
* {@inheritdoc}
5555
*/
5656
public function request(string $method, string $url, array $options = []): ResponseInterface
5757
{
58-
[$url, $options] = $this->prepareRequest($method, $url, $options, ['base_uri' => $this->baseUri], true);
58+
[$url, $options] = $this->prepareRequest($method, $url, $options, $this->defaultOptions, true);
5959
$url = implode('', $url);
6060

6161
if (null === $this->responseFactory) {
@@ -96,4 +96,15 @@ public function getRequestsCount(): int
9696
{
9797
return $this->requestsCount;
9898
}
99+
100+
/**
101+
* {@inheritdoc}
102+
*/
103+
public function withOptions(array $options): self
104+
{
105+
$clone = clone $this;
106+
$clone->defaultOptions = self::mergeDefaultOptions($options, $this->defaultOptions, true);
107+
108+
return $clone;
109+
}
99110
}

NoPrivateNetworkHttpClient.php

+11
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,15 @@ public function setLogger(LoggerInterface $logger): void
110110
$this->client->setLogger($logger);
111111
}
112112
}
113+
114+
/**
115+
* {@inheritdoc}
116+
*/
117+
public function withOptions(array $options): self
118+
{
119+
$clone = clone $this;
120+
$clone->client = $this->client->withOptions($options);
121+
122+
return $clone;
123+
}
113124
}

ScopingHttpClient.php

+11
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,15 @@ public function setLogger(LoggerInterface $logger): void
110110
$this->client->setLogger($logger);
111111
}
112112
}
113+
114+
/**
115+
* {@inheritdoc}
116+
*/
117+
public function withOptions(array $options): self
118+
{
119+
$clone = clone $this;
120+
$clone->client = $this->client->withOptions($options);
121+
122+
return $clone;
123+
}
113124
}

TraceableHttpClient.php

+11
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,15 @@ public function setLogger(LoggerInterface $logger): void
105105
$this->client->setLogger($logger);
106106
}
107107
}
108+
109+
/**
110+
* {@inheritdoc}
111+
*/
112+
public function withOptions(array $options): self
113+
{
114+
$clone = clone $this;
115+
$clone->client = $this->client->withOptions($options);
116+
117+
return $clone;
118+
}
108119
}

composer.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
"php-http/async-client-implementation": "*",
1919
"php-http/client-implementation": "*",
2020
"psr/http-client-implementation": "1.0",
21-
"symfony/http-client-implementation": "2.2"
21+
"symfony/http-client-implementation": "2.4"
2222
},
2323
"require": {
2424
"php": ">=7.2.5",
2525
"psr/log": "^1.0",
26-
"symfony/http-client-contracts": "^2.2",
26+
"symfony/http-client-contracts": "^2.4",
2727
"symfony/polyfill-php73": "^1.11",
2828
"symfony/polyfill-php80": "^1.15",
2929
"symfony/service-contracts": "^1.0|^2"

0 commit comments

Comments
 (0)