8000 minor #50225 [HttpClient] Favor php-http/discovery instead of nyholm/… · symfony/symfony@70b40fc · GitHub
[go: up one dir, main page]

Skip to content

Commit 70b40fc

Browse files
minor #50225 [HttpClient] Favor php-http/discovery instead of nyholm/psr7 (nicolas-grekas)
This PR was merged into the 6.3 branch. Discussion ---------- [HttpClient] Favor php-http/discovery instead of nyholm/psr7 | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - This PR fine-tunes the DX related to using `HttplugClient` and `Psr18Client`. By favoring `php-http/discovery`, we build on [its latest capabilities](https://github.com/php-http/discovery/releases) to use whatever implementation might be installed and preferred by the app. Of course, we keep `nyholm/psr7` as a privileged PSR-7 implementation so that when it's installed but `php-http/discovery` is not, things keep working as usual. The deprecated interfaces from `php-http/message-factory` are also moved to a new conditional and internal `LegacyHttplugInterface`, so that we can make this dependency optional. Commits ------- 5733ff7 [HttpClient] Favor php-http/discovery instead of nyholm/psr7
2 parents 0d25263 + 5733ff7 commit 70b40fc

File tree

7 files changed

+99
-70
lines changed

7 files changed

+99
-70
lines changed

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
"monolog/monolog": "^1.25.1|^2",
142142
"nyholm/psr7": "^1.0",
143143
"pda/pheanstalk": "^4.0",
144+
"php-http/discovery": "^1.15",
144145
"php-http/httplug": "^1.0|^2.0",
145146
"php-http/message-factory": "^1.0",
146147
"phpdocumentor/reflection-docblock": "^5.2",
@@ -171,6 +172,7 @@
171172
},
172173
"config": {
173174
"allow-plugins": {
175+
"php-http/discovery": false,
174176
"symfony/runtime": true
175177
}
176178
},

src/Symfony/Component/ErrorHandler/DebugClassLoader.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use Prophecy\Prophecy\ProphecySubjectInterface;
2222
use ProxyManager\Proxy\ProxyInterface;
2323
use Symfony\Component\ErrorHandler\Internal\TentativeTypes;
24-
use Symfony\Component\HttpClient\HttplugClient;
2524
use Symfony\Component\VarExporter\LazyObjectInterface;
2625

2726
/**
@@ -422,9 +421,7 @@ public function checkAnnotations(\ReflectionClass $refl, string $class): array
422421
if (!isset(self::$checkedClasses[$use])) {
423422
$this->checkClass($use);
424423
}
425-
if (isset(self::$deprecated[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && !isset(self::$deprecated[$class])
426-
&& !(HttplugClient::class === $class && \in_array($use, [\Http\Client\HttpClient::class, \Http\Message\RequestFactory::class, \Http\Message\StreamFactory::class, \Http\Message\UriFactory::class], true))
427-
) {
424+
if (isset(self::$deprecated[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && !isset(self::$deprecated[$class])) {
428425
$type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait');
429426
$verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
430427

src/Symfony/Component/HttpClient/HttplugClient.php

Lines changed: 27 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,9 @@
1717
use Http\Client\Exception\NetworkException;
1818
use Http\Client\Exception\RequestException;
1919
use Http\Client\HttpAsyncClient;
20-
use Http\Client\HttpClient as HttplugInterface;
21-
use Http\Discovery\Exception\NotFoundException;
20+
use Http\Discovery\Psr17Factory;
2221
use Http\Discovery\Psr17FactoryDiscovery;
23-
use Http\Message\RequestFactory;
24-
use Http\Message\StreamFactory;
25-
use Http\Message\UriFactory;
26-
use Nyholm\Psr7\Factory\Psr17Factory;
22+
use Nyholm\Psr7\Factory\Psr17Factory as NyholmPsr17Factory;
2723
use Nyholm\Psr7\Request;
2824
use Nyholm\Psr7\Uri;
2925
use Psr\Http\Client\ClientInterface;
@@ -36,37 +32,32 @@
3632
use Psr\Http\Message\UriFactoryInterface;
3733
use Psr\Http\Message\UriInterface;
3834
use Symfony\Component\HttpClient\Internal\HttplugWaitLoop;
35+
use Symfony\Component\HttpClient\Internal\LegacyHttplugInterface;
3936
use Symfony\Component\HttpClient\Response\HttplugPromise;
4037
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
4138
use Symfony\Contracts\HttpClient\HttpClientInterface;
4239
use Symfony\Contracts\HttpClient\ResponseInterface;
4340
use Symfony\Contracts\Service\ResetInterface;
4441

45-
if (!interface_exists(HttplugInterface::class)) {
46-
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/httplug" package is not installed. Try running "composer require php-http/httplug".');
47-
}
48-
49-
if (!interface_exists(RequestFactory::class)) {
50-
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/message-factory" package is not installed. Try running "composer require php-http/message-factory".');
42+
if (!interface_exists(HttpAsyncClient::class)) {
43+
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "php-http/httplug" package is not installed. Try running "php-http/discovery php-http/async-client-implementation:*".');
5144
}
5245

5346
if (!interface_exists(RequestFactoryInterface::class)) {
54-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as the "psr/http-factory" package is not installed. Try running "composer require nyholm/psr7".');
55-
}
56-
57-
if (!interface_exists(ClientInterface::class)) {
58-
throw new \LogicException('You cannot use "Symfony\Component\HttpClient\HttplugClient" as the "psr/http-client" package is not installed. Try running "composer require psr/http-client".');
47+
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as the "psr/http-factory" package is not installed. Try running "composer require php-http/discovery psr/http-factory-implementation:*".');
5948
}
6049

6150
/**
6251
* An adapter to turn a Symfony HttpClientInterface into an Httplug client.
6352
*
64-
* Run "composer require nyholm/psr7" to install an efficient implementation of response
65-
* and stream factories with flex-provided autowiring aliases.
53+
* In comparison to Psr18Client, this client supports asynchronous requests.
54+
*
55+
* Run "composer require php-http/discovery php-http/async-client-implementation:*"
56+
* to get the required dependencies.
6657
*
6758
* @author Nicolas Grekas <p@tchwork.com>
6859
*/
69-
final class HttplugClient implements ClientInterface, HttplugInterface, HttpAsyncClient, RequestFactoryInterface, StreamFactoryInterface, UriFactoryInterface, RequestFactory, StreamFactory, UriFactory, ResetInterface
60+
final class HttplugClient implements ClientInterface, HttpAsyncClient, RequestFactoryInterface, StreamFactoryInterface, UriFactoryInterface, ResetInterface, LegacyHttplugInterface
7061
{
7162
private HttpClientInterface $client;
7263
private ResponseFactoryInterface $responseFactory;
@@ -86,17 +77,16 @@ public function __construct(HttpClientInterface $client = null, ResponseFactoryI
8677
$this->promisePool = class_exists(Utils::class) ? new \SplObjectStorage() : null;
8778

8879
if (null === $responseFactory || null === $streamFactory) {
89-
if (!class_exists(Psr17Factory::class) && !class_exists(Psr17FactoryDiscovery::class)) {
90-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
80+
if (class_exists(Psr17Factory::class)) {
81+
$psr17Factory = new Psr17Factory();
82+
} elseif (class_exists(NyholmPsr17Factory::class)) {
83+
$psr17Factory = new NyholmPsr17Factory();
84+
} else {
85+
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been provided. Try running "composer require php-http/discovery psr/http-factory-implementation:*".');
9186
}
9287

93-
try {
94-
$psr17Factory = class_exists(Psr17Factory::class, false) ? new Psr17Factory() : null;
95-
$responseFactory ??= $psr17Factory ?? Psr17FactoryDiscovery::findResponseFactory();
96-
$streamFactory ??= $psr17Factory ?? Psr17FactoryDiscovery::findStreamFactory();
97-
} catch (NotFoundException $e) {
98-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been found. Try running "composer require nyholm/psr7".', 0, $e);
99-
}
88+
$responseFactory ??= $psr17Factory;
89+
$streamFactory ??= $psr17Factory;
10090
}
10191

10292
$this->responseFactory = $responseFactory;
@@ -170,12 +160,12 @@ public function createRequest($method, $uri, array $headers = [], $body = null,
170160
}
171161
if ($this->responseFactory instanceof RequestFactoryInterface) {
172162
$request = $this->responseFactory->createRequest($method, $uri);
173-
} elseif (class_exists(Request::class)) {
174-
$request = new Request($method, $uri);
175163
} elseif (class_exists(Psr17FactoryDiscovery::class)) {
176164
$request = Psr17FactoryDiscovery::findRequestFactory()->createRequest($method, $uri);
165+
} elseif (class_exists(Request::class)) {
166+
$request = new Request($method, $uri);
177167
} else {
178-
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
168+
throw new \LogicException(sprintf('You cannot use "%s()" as no PSR-17 factories have been found. Try running "composer require php-http/discovery psr/http-factory-implementation:*".', __METHOD__));
179169
}
180170

181171
$request = $request
@@ -245,15 +235,15 @@ public function createUri($uri = ''): UriInterface
245235
return $this->responseFactory->createUri($uri);
246236
}
247237

248-
if (class_exists(Uri::class)) {
249-
return new Uri($uri);
250-
}
251-
252238
if (class_exists(Psr17FactoryDiscovery::class)) {
253239
return Psr17FactoryDiscovery::findUrlFactory()->createUri($uri);
254240
}
255241

256-
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
242+
if (class_exists(Uri::class)) {
243+
return new Uri($uri);
244+
}
245+
246+
throw new \LogicException(sprintf('You cannot use "%s()" as no PSR-17 factories have been found. Try running "composer require php-http/discovery psr/http-factory-implementation:*".', __METHOD__));
257247
}
258248

259249
public function __sleep(): array
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpClient\Internal;
13+
14+
use Http\Client\HttpClient;
15+
use Http\Message\RequestFactory;
16+
use Http\Message\StreamFactory;
17+
use Http\Message\UriFactory;
18+
19+
if (interface_exists(RequestFactory::class)) {
20+
/**
21+
* @internal
22+
*
23+
* @deprecated since Symfony 6.3
24+
*/
25+
interface LegacyHttplugInterface extends HttpClient, RequestFactory, StreamFactory, UriFactory
26+
{
27+
}
28+
} else {
29+
/**
30+
* @internal
31+
*
32+
* @deprecated since Symfony 6.3
33+
*/
34+
interface LegacyHttplugInterface extends HttpClient
35+
{
36+
}
37+
}

src/Symfony/Component/HttpClient/Psr18Client.php

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
namespace Symfony\Component\HttpClient;
1313

14-
use Http\Discovery\Exception\NotFoundException;
14+
use Http\Discovery\Psr17Factory;
1515
use Http\Discovery\Psr17FactoryDiscovery;
16-
use Nyholm\Psr7\Factory\Psr17Factory;
16+
use Nyholm\Psr7\Factory\Psr17Factory as NyholmPsr17Factory;
1717
use Nyholm\Psr7\Request;
1818
use Nyholm\Psr7\Uri;
1919
use Psr\Http\Client\ClientInterface;
@@ -33,20 +33,19 @@
3333
use Symfony\Contracts\HttpClient\HttpClientInterface;
3434
use Symfony\Contracts\Service\ResetInterface;
3535

36-
if (!interface_exists(RequestFactoryInterface::class)) {
37-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as the "psr/http-factory" package is not installed. Try running "composer require nyholm/psr7".');
36+
if (!interface_exists(ClientInterface::class)) {
37+
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as the "psr/http-client" package is not installed. Try running "composer require php-http/discovery psr/http-client-implementation:*".');
3838
}
3939

40-
if (!interface_exists(ClientInterface::class)) {
41-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as the "psr/http-client" package is not installed. Try running "composer require psr/http-client".');
40+
if (!interface_exists(RequestFactoryInterface::class)) {
41+
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as the "psr/http-factory" package is not installed. Try running "composer require php-http/discovery psr/http-factory-implementation:*".');
4242
}
4343

4444
/**
4545
* An adapter to turn a Symfony HttpClientInterface into a PSR-18 ClientInterface.
4646
*
47-
* Run "composer require psr/http-client" to install the base ClientInterface. Run
48-
* "composer require nyholm/psr7" to install an efficient implementation of response
49-
* and stream factories with flex-provided autowiring aliases.
47+
* Run "composer require php-http/discovery psr/http-client-implementation:*"
48+
* to get the required dependencies.
5049
*
5150
* @author Nicolas Grekas <p@tchwork.com>
5251
*/
@@ -62,17 +61,16 @@ public function __construct(HttpClientInterface $client = null, ResponseFactoryI
6261
$streamFactory ??= $responseFactory instanceof StreamFactoryInterface ? $responseFactory : null;
6362

6463
if (null === $responseFactory || null === $streamFactory) {
65-
if (!class_exists(Psr17Factory::class) && !class_exists(Psr17FactoryDiscovery::class)) {
66-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
64+
if (class_exists(Psr17Factory::class)) {
65+
$psr17Factory = new Psr17Factory();
66+
} elseif (class_exists(NyholmPsr17Factory::class)) {
67+
$psr17Factory = new NyholmPsr17Factory();
68+
} else {
69+
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as no PSR-17 factories have been provided. Try running "composer require php-http/discovery psr/http-factory-implementation:*".');
6770
}
6871

69-
try {
70-
$psr17Factory = class_exists(Psr17Factory::class, false) ? new Psr17Factory() : null;
71-
$responseFactory ??= $psr17Factory ?? Psr17FactoryDiscovery::findResponseFactory();
72-
$streamFactory ??= $psr17Factory ?? Psr17FactoryDiscovery::findStreamFactory();
73-
} catch (NotFoundException $e) {
74-
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been found. Try running "composer require nyholm/psr7".', 0, $e);
75-
}
72+
$responseFactory ??= $psr17Factory;
73+
$streamFactory ??= $psr17Factory;
7674
}
7775

7876
$this->responseFactory = $responseFactory;
@@ -142,15 +140,15 @@ public function createRequest(string $method, $uri): RequestInterface
142140
return $this->responseFactory->createRequest($method, $uri);
143141
}
144142

145-
if (class_exists(Request::class)) {
146-
return new Request($method, $uri);
147-
}
148-
149143
if (class_exists(Psr17FactoryDiscovery::class)) {
150144
return Psr17FactoryDiscovery::findRequestFactory()->createRequest($method, $uri);
151145
}
152146

153-
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
147+
if (class_exists(Request::class)) {
148+
return new Request($method, $uri);
149+
}
150+
151+
throw new \LogicException(sprintf('You cannot use "%s()" as no PSR-17 factories have been found. Try running "composer require php-http/discovery psr/http-factory-implementation:*".', __METHOD__));
154152
}
155153

156154
public function createStream(string $content = ''): StreamInterface
@@ -180,15 +178,15 @@ public function createUri(string $uri = ''): UriInterface
180178
return $this->responseFactory->createUri($uri);
181179
}
182180

183-
if (class_exists(Uri::class)) {
184-
return new Uri($uri);
185-
}
186-
187181
if (class_exists(Psr17FactoryDiscovery::class)) {
188182
return Psr17FactoryDiscovery::findUrlFactory()->createUri($uri);
189183
}
190184

191-
throw new \LogicException(sprintf('You cannot use "%s()" as the "nyholm/psr7" package is not installed. Try running "composer require nyholm/psr7".', __METHOD__));
185+
if (class_exists(Uri::class)) {
186+
return new Uri($uri);
187+
}
188+
189+
throw new \LogicException(sprintf('You cannot use "%s()" as no PSR-17 factories have been found. Try running "composer require php-http/discovery psr/http-factory-implementation:*".', __METHOD__));
192190
}
193191

194192
public function reset(): void

src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ public function testNormalizeBodyMultipartForwardStream($stream)
156156
public static function provideNormalizeBodyMultipartForwardStream()
157157
{
158158
yield 'native' => [fopen('https://github.githubassets.com/images/icons/emoji/unicode/1f44d.png', 'r')];
159+
160+
if (!\defined('OPENSSL_DEFAULT_STREAM_CIPHERS')) {
161+
return;
162+
}
163+
159164
yield 'symfony' => [HttpClient::create()->request('GET', 'https://github.githubassets.com/images/icons/emoji/unicode/1f44d.png')->toStream()];
160165
}
161166

src/Symfony/Component/HttpClient/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@
3636
"guzzlehttp/promises": "^1.4",
3737
"nyholm/psr7": "^1.0",
3838
"php-http/httplug": "^1.0|^2.0",
39-
"php-http/message-factory": "^1.0",
4039
"psr/http-client": "^1.0",
4140
"symfony/dependency-injection": "^5.4|^6.0",
4241
"symfony/http-kernel": "^5.4|^6.0",
4342
"symfony/process": "^5.4|^6.0",
4443
"symfony/stopwatch": "^5.4|^6.0"
4544
},
4645
"conflict": {
46+
"php-http/discovery": "<1.15",
4747
"symfony/http-foundation": "<6.3"
4848
},
4949
"autoload": {

0 commit comments

Comments
 (0)
0