12
12
namespace Symfony \Component \HttpClient ;
13
13
14
14
use Amp \CancelledException ;
15
+ use Amp \DeferredFuture ;
15
16
use Amp \Http \Client \DelegateHttpClient ;
16
17
use Amp \Http \Client \InterceptedHttpClient ;
17
18
use Amp \Http \Client \PooledHttpClient ;
18
19
use Amp \Http \Client \Request ;
20
+ use Amp \Http \HttpMessage ;
19
21
use Amp \Http \Tunnel \Http1TunnelConnector ;
20
- use Amp \Promise ;
21
22
use Psr \Log \LoggerAwareInterface ;
22
23
use Psr \Log \LoggerAwareTrait ;
23
24
use Symfony \Component \HttpClient \Exception \TransportException ;
24
- use Symfony \Component \HttpClient \Internal \AmpClientState ;
25
- use Symfony \Component \HttpClient \Response \AmpResponse ;
25
+ use Symfony \Component \HttpClient \Internal \AmpClientStateV4 ;
26
+ use Symfony \Component \HttpClient \Internal \AmpClientStateV5 ;
27
+ use Symfony \Component \HttpClient \Response \AmpResponseV4 ;
28
+ use Symfony \Component \HttpClient \Response \AmpResponseV5 ;
26
29
use Symfony \Component \HttpClient \Response \ResponseStream ;
27
30
use Symfony \Contracts \HttpClient \HttpClientInterface ;
28
31
use Symfony \Contracts \HttpClient \ResponseInterface ;
33
36
throw new \LogicException ('You cannot use "Symfony\Component\HttpClient\AmpHttpClient" as the "amphp/http-client" package is not installed. Try running "composer require amphp/http-client:^4.2.1". ' );
34
37
}
35
38
36
- if (! interface_exists (Promise ::class)) {
37
- throw new \LogicException ('You cannot use "Symfony\Component\HttpClient\AmpHttpClient" as the installed " amphp/http-client" is not compatible with this version of "symfony/http-client". Try downgrading " amphp/http-client" to " ^4.2.1". ' );
39
+ if (\ PHP_VERSION_ID < 80400 && is_subclass_of (Request::class, HttpMessage ::class)) {
40
+ throw new \LogicException ('Using "Symfony\Component\HttpClient\AmpHttpClient" with amphp/http-client >= 5 requires PHP >= 8.4. Try running "composer require amphp/http-client: ^4.2.1" or upgrade to PHP >= 8.4 . ' );
38
41
}
39
42
40
43
/**
@@ -53,7 +56,7 @@ final class AmpHttpClient implements HttpClientInterface, LoggerAwareInterface,
53
56
54
57
private array $ defaultOptions = self ::OPTIONS_DEFAULTS ;
55
58
private static array $ emptyDefaults = self ::OPTIONS_DEFAULTS ;
56
- private AmpClientState $ multi ;
59
+ private AmpClientStateV4 | AmpClientStateV5 $ multi ;
57
60
58
61
/**
59
62
* @param array $defaultOptions Default requests' options
@@ -72,7 +75,11 @@ public function __construct(array $defaultOptions = [], ?callable $clientConfigu
72
75
[, $ this ->defaultOptions ] = self ::prepareRequest (null , null , $ defaultOptions , $ this ->defaultOptions );
73
76
}
74
77
75
- $ this ->multi = new AmpClientState ($ clientConfigurator , $ maxHostConnections , $ maxPendingPushes , $ this ->logger );
78
+ if (is_subclass_of (Request::class, HttpMessage::class)) {
79
+ $ this ->multi = new AmpClientStateV5 ($ clientConfigurator , $ maxHostConnections , $ maxPendingPushes , $ this ->logger );
80
+ } else {
81
+ $ this ->multi = new AmpClientStateV4 ($ clientConfigurator , $ maxHostConnections , $ maxPendingPushes , $ this ->logger );
82
+ }
76
83
}
77
84
78
85
/**
@@ -132,9 +139,10 @@ public function request(string $method, string $url, array $options = []): Respo
132
139
$ request ->addHeader ($ h [0 ], $ h [1 ]);
133
140
}
134
141
135
- $ request ->setTcpConnectTimeout (1000 * $ options ['timeout ' ]);
136
- $ request ->setTlsHandshakeTimeout (1000 * $ options ['timeout ' ]);
137
- $ request ->setTransferTimeout (1000 * $ options ['max_duration ' ]);
142
+ $ coef = $ request instanceof HttpMessage ? 1 : 1000 ;
143
+ $ request ->setTcpConnectTimeout ($ coef * $ options ['timeout ' ]);
144
+ $ request ->setTlsHandshakeTimeout ($ coef * $ options ['timeout ' ]);
145
+ $ request ->setTransferTimeout ($ coef * $ options ['max_duration ' ]);
138
146
if (method_exists ($ request , 'setInactivityTimeout ' )) {
139
147
$ request ->setInactivityTimeout (0 );
140
148
}
@@ -145,25 +153,37 @@ public function request(string $method, string $url, array $options = []): Respo
145
153
$ request ->setHeader ('Authorization ' , 'Basic ' .base64_encode (implode (': ' , $ auth )));
146
154
}
147
155
148
- return new AmpResponse ($ this ->multi , $ request , $ options , $ this ->logger );
156
+ if ($ request instanceof HttpMessage) {
157
+ return new AmpResponseV5 ($ this ->multi , $ request , $ options , $ this ->logger );
158
+ }
159
+
160
+ return new AmpResponseV4 ($ this ->multi , $ request , $ options , $ this ->logger );
149
161
}
150
162
151
163
public function stream (ResponseInterface |iterable $ responses , ?float $ timeout = null ): ResponseStreamInterface
152
164
{
153
- if ($ responses instanceof AmpResponse ) {
165
+ if ($ responses instanceof AmpResponseV4 || $ responses instanceof AmpResponseV5 ) {
154
166
$ responses = [$ responses ];
155
167
}
156
168
157
- return new ResponseStream (AmpResponse::stream ($ responses , $ timeout ));
169
+ if ($ this ->multi instanceof AmpClientStateV5) {
170
+ return new ResponseStream (AmpResponseV5::stream ($ responses , $ timeout ));
171
+ }
172
+
173
+ return new ResponseStream (AmpResponseV4::stream ($ responses , $ timeout ));
158
174
}
159
175
160
176
public function reset (): void
161
177
{
162
178
$ this ->multi ->dnsCache = [];
163
179
164
- foreach ($ this ->multi ->pushedResponses as $ authority => $ pushedResponses ) {
180
+ foreach ($ this ->multi ->pushedResponses as $ pushedResponses ) {
165
181
foreach ($ pushedResponses as [$ pushedUrl , $ pushDeferred ]) {
166
- $ pushDeferred ->fail (new CancelledException ());
182
+ if ($ pushDeferred instanceof DeferredFuture) {
183
+ $ pushDeferred ->error (new CancelledException ());
184
+ } else {
185
+ $ pushDeferred ->fail (new CancelledException ());
186
+ }
167
187
168
188
$ this ->logger ?->debug(\sprintf ('Unused pushed response: "%s" ' , $ pushedUrl ));
169
189
}
0 commit comments