Skip to content

Commit 3682dd5

Browse files
committed
Merge branch '7.4' into 8.0
* 7.4: [Console] ensure `SHELL_VERBOSITY` is always restored properly [Console] Add support for `Cursor` helper in invokable commands [MonologBridge] Improve error when HttpClient contract is installed but not the component simplify LogoutListenerTest forbid HTTP method override of GET, HEAD, CONNECT and TRACE [HttpClient] Add option `auto_upgrade_http_version` to control how the request HTTP version is handled in `HttplugClient` and `Psr18Client` [Security] Allow multiple OIDC discovery endpoints [AssetMapper] Fix links to propshaft Document BC break in AbstractController::render
2 parents 2350540 + bd7c469 commit 3682dd5

File tree

5 files changed

+77
-4
lines changed

5 files changed

+77
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ CHANGELOG
1414
* Deprecate using amphp/http-client < 5
1515
* Add RFC 9111–based caching support to `CachingHttpClient`
1616
* Deprecate passing an instance of `StoreInterface` as `$cache` argument to `CachingHttpClient` constructor
17+
* Add option `auto_upgrade_http_version` to control how the request HTTP version is handled in `HttplugClient` and `Psr18Client`
1718

1819
7.3
1920
---

HttplugClient.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ final class HttplugClient implements ClientInterface, HttpAsyncClient, RequestFa
6161
private HttpClientInterface $client;
6262
private ResponseFactoryInterface $responseFactory;
6363
private StreamFactoryInterface $streamFactory;
64+
private bool $autoUpgradeHttpVersion = true;
6465

6566
/**
6667
* @var \SplObjectStorage<ResponseInterface, array{RequestInterface, Promise}>|null
@@ -96,6 +97,10 @@ public function __construct(?HttpClientInterface $client = null, ?ResponseFactor
9697
public function withOptions(array $options): static
9798
{
9899
$clone = clone $this;
100+
if (\array_key_exists('auto_upgrade_http_version', $options)) {
101+
$clone->autoUpgradeHttpVersion = $options['auto_upgrade_http_version'];
102+
unset($options['auto_upgrade_http_version']);
103+
}
99104
$clone->client = $clone->client->withOptions($options);
100105

101106
return $clone;
@@ -265,8 +270,8 @@ private function sendPsr7Request(RequestInterface $request, ?bool $buffer = null
265270
'buffer' => $buffer,
266271
];
267272

268-
if ('1.0' === $request->getProtocolVersion()) {
269-
$options['http_version'] = '1.0';
273+
if (!$this->autoUpgradeHttpVersion || '1.0' === $request->getProtocolVersion()) {
274+
$options['http_version'] = $request->getProtocolVersion();
270275
}
271276

272277
return $this->client->request($request->getMethod(), (string) $request->getUri(), $options);

Psr18Client.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str
5353
private HttpClientInterface $client;
5454
private ResponseFactoryInterface $responseFactory;
5555
private StreamFactoryInterface $streamFactory;
56+
private bool $autoUpgradeHttpVersion = true;
5657

5758
public function __construct(?HttpClientInterface $client = null, ?ResponseFactoryInterface $responseFactory = null, ?StreamFactoryInterface $streamFactory = null)
5859
{
@@ -79,6 +80,10 @@ public function __construct(?HttpClientInterface $client = null, ?ResponseFactor
7980
public function withOptions(array $options): static
8081
{
8182
$clone = clone $this;
83+
if (\array_key_exists('auto_upgrade_http_version', $options)) {
84+
$clone->autoUpgradeHttpVersion = $options['auto_upgrade_http_version'];
85+
unset($options['auto_upgrade_http_version']);
86+
}
8287
$clone->client = $clone->client->withOptions($options);
8388

8489
return $clone;
@@ -128,8 +133,8 @@ public function sendRequest(RequestInterface $request): ResponseInterface
128133
'body' => $body,
129134
];
130135

131-
if ('1.0' === $request->getProtocolVersion()) {
132-
$options['http_version'] = '1.0';
136+
if (!$this->autoUpgradeHttpVersion || '1.0' === $request->getProtocolVersion()) {
137+
$options['http_version'] = $request->getProtocolVersion();
133138
}
134139

135140
$response = $this->client->request($request->getMethod(), (string) $request->getUri(), $options);

Tests/HttplugClientTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,4 +299,35 @@ public function testResponseReasonPhrase()
299299
$resultResponse = $client->sendRequest($request);
300300
$this->assertSame('Very Early Hints', $resultResponse->getReasonPhrase());
301301
}
302+
303+
public function testAutoUpgradeHttpVersion()
304+
{
305+
$clientWithoutOption = new HttplugClient(new MockHttpClient(function (string $method, string $url, array $options) {
306+
return new MockResponse(json_encode([
307+
'SERVER_PROTOCOL' => 'HTTP/'.$options['http_version'] ?? '',
308+
]), [
309+
'response_headers' => [
310+
'Content-Type' => 'application/json',
311+
],
312+
]);
313+
}));
314+
$clientWithOptionFalse = $clientWithoutOption->withOptions(['auto_upgrade_http_version' => false]);
315+
316+
foreach (['1.0', '1.1', '2.0', '3.0'] as $httpVersion) {
317+
$request = $clientWithoutOption->createRequest('GET', 'http://localhost:8057')
318+
->withProtocolVersion($httpVersion);
319+
320+
$responseWithoutOption = $clientWithoutOption->sendRequest($request);
321+
$bodyWithoutOption = json_decode((string) $responseWithoutOption->getBody(), true);
322+
if ('1.0' === $httpVersion) {
323+
$this->assertSame('HTTP/1.0', $bodyWithoutOption['SERVER_PROTOCOL']);
324+
} else {
325+
$this->assertSame('HTTP/', $bodyWithoutOption['SERVER_PROTOCOL']);
326+
}
327+
328+
$responseWithOptionFalse = $clientWithOptionFalse->sendRequest($request);
329+
$bodyWithOptionFalse = json_decode((string) $responseWithOptionFalse->getBody(), true);
330+
$this->assertSame('HTTP/'.$httpVersion, $bodyWithOptionFalse['SERVER_PROTOCOL']);
331+
}
332+
}
302333
}

Tests/Psr18ClientTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,35 @@ public function testResponseReasonPhrase()
118118
$resultResponse = $client->sendRequest($request);
119119
$this->assertSame('Very Early Hints', $resultResponse->getReasonPhrase());
120120
}
121+
122+
public function testAutoUpgradeHttpVersion()
123+
{
124+
$clientWithoutOption = new Psr18Client(new MockHttpClient(function (string $method, string $url, array $options) {
125+
return new MockResponse(json_encode([
126+
'SERVER_PROTOCOL' => 'HTTP/'.$options['http_version'] ?? '',
127+
]), [
128+
'response_headers' => [
129+
'Content-Type' => 'application/json',
130+
],
131+
]);
132+
}));
133+
$clientWithOptionFalse = $clientWithoutOption->withOptions(['auto_upgrade_http_version' => false]);
134+
135+
foreach (['1.0', '1.1', '2.0', '3.0'] as $httpVersion) {
136+
$request = $clientWithoutOption->createRequest('GET', 'http://localhost:8057')
137+
->withProtocolVersion($httpVersion);
138+
139+
$responseWithoutOption = $clientWithoutOption->sendRequest($request);
140+
$bodyWithoutOption = json_decode((string) $responseWithoutOption->getBody(), true);
141+
if ('1.0' === $httpVersion) {
142+
$this->assertSame('HTTP/1.0', $bodyWithoutOption['SERVER_PROTOCOL']);
143+
} else {
144+
$this->assertSame('HTTP/', $bodyWithoutOption['SERVER_PROTOCOL']);
145+
}
146+
147+
$responseWithOptionFalse = $clientWithOptionFalse->sendRequest($request);
148+
$bodyWithOptionFalse = json_decode((string) $responseWithOptionFalse->getBody(), true);
149+
$this->assertSame('HTTP/'.$httpVersion, $bodyWithOptionFalse['SERVER_PROTOCOL']);
150+
}
151+
}
121152
}

0 commit comments

Comments
 (0)