Skip to content

Commit ee12067

Browse files
[HttpClient] Favor php-http/discovery instead of nyholm/psr7
1 parent 980959b commit ee12067

File tree

5 files changed

+96
-66
lines changed

5 files changed

+96
-66
lines changed

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

Internal/LegacyHttplugInterface.php

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+
}

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

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

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)