@@ -46,6 +46,16 @@ public function __construct(int $maxHandles)
46
46
47
47
public function create (RequestInterface $ request , array $ options ): EasyHandle
48
48
{
49
+ $ protocolVersion = $ request ->getProtocolVersion ();
50
+
51
+ if ('2 ' === $ protocolVersion || '2.0 ' === $ protocolVersion ) {
52
+ if (!self ::supportsHttp2 ()) {
53
+ throw new ConnectException ('HTTP/2 is supported by the cURL handler, however libcurl is built without HTTP/2 support. ' , $ request );
54
+ }
55
+ } elseif ('1.0 ' !== $ protocolVersion && '1.1 ' !== $ protocolVersion ) {
56
+ throw new ConnectException (sprintf ('HTTP/%s is not supported by the cURL handler. ' , $ protocolVersion ), $ request );
57
+ }
58
+
49
59
if (isset ($ options ['curl ' ]['body_as_string ' ])) {
50
60
$ options ['_body_as_string ' ] = $ options ['curl ' ]['body_as_string ' ];
51
61
unset($ options ['curl ' ]['body_as_string ' ]);
@@ -72,6 +82,42 @@ public function create(RequestInterface $request, array $options): EasyHandle
72
82
return $ easy ;
73
83
}
74
84
85
+ private static function supportsHttp2 (): bool
86
+ {
87
+ static $ supportsHttp2 = null ;
88
+
89
+ if (null === $ supportsHttp2 ) {
90
+ $ supportsHttp2 = self ::supportsTls12 ()
91
+ && defined ('CURL_VERSION_HTTP2 ' )
92
+ && (\CURL_VERSION_HTTP2 & \curl_version ()['features ' ]);
93
+ }
94
+
95
+ return $ supportsHttp2 ;
96
+ }
97
+
98
+ private static function supportsTls12 (): bool
99
+ {
100
+ static $ supportsTls12 = null ;
101
+
102
+ if (null === $ supportsTls12 ) {
103
+ $ supportsTls12 = \CURL_SSLVERSION_TLSv1_2 & \curl_version ()['features ' ];
104
+ }
105
+
106
+ return $ supportsTls12 ;
107
+ }
108
+
109
+ private static function supportsTls13 (): bool
110
+ {
111
+ static $ supportsTls13 = null ;
112
+
113
+ if (null === $ supportsTls13 ) {
114
+ $ supportsTls13 = defined ('CURL_SSLVERSION_TLSv1_3 ' )
115
+ && (\CURL_SSLVERSION_TLSv1_3 & \curl_version ()['features ' ]);
116
+ }
117
+
118
+ return $ supportsTls13 ;
119
+ }
120
+
75
121
public function release (EasyHandle $ easy ): void
76
122
{
77
123
$ resource = $ easy ->handle ;
@@ -147,7 +193,7 @@ private static function finishError(callable $handler, EasyHandle $easy, CurlFac
147
193
'error ' => \curl_error ($ easy ->handle ),
148
194
'appconnect_time ' => \curl_getinfo ($ easy ->handle , \CURLINFO_APPCONNECT_TIME ),
149
195
] + \curl_getinfo ($ easy ->handle );
150
- $ ctx [self ::CURL_VERSION_STR ] = \curl_version ()[ ' version ' ] ;
196
+ $ ctx [self ::CURL_VERSION_STR ] = self :: getCurlVersion () ;
151
197
$ factory ->release ($ easy );
152
198
153
199
// Retry when nothing is present or when curl failed to rewind.
@@ -158,6 +204,17 @@ private static function finishError(callable $handler, EasyHandle $easy, CurlFac
158
204
return self ::createRejection ($ easy , $ ctx );
159
205
}
160
206
207
+ private static function getCurlVersion (): string
208
+ {
209
+ static $ curlVersion = null ;
210
+
211
+ if (null === $ curlVersion ) {
212
+ $ curlVersion = \curl_version ()['version ' ];
213
+ }
214
+
215
+ return $ curlVersion ;
216
+ }
217
+
161
218
private static function createRejection (EasyHandle $ easy , array $ ctx ): PromiseInterface
162
219
{
163
220
static $ connectionErrors = [
@@ -232,10 +289,11 @@ private function getDefaultConf(EasyHandle $easy): array
232
289
}
233
290
234
291
$ version = $ easy ->request ->getProtocolVersion ();
235
- if ($ version == 1.1 ) {
236
- $ conf [\CURLOPT_HTTP_VERSION ] = \CURL_HTTP_VERSION_1_1 ;
237
- } elseif ($ version == 2.0 ) {
292
+
293
+ if ('2 ' === $ version || '2.0 ' === $ version ) {
238
294
$ conf [\CURLOPT_HTTP_VERSION ] = \CURL_HTTP_VERSION_2_0 ;
295
+ } elseif ('1.1 ' === $ version ) {
296
+ $ conf [\CURLOPT_HTTP_VERSION ] = \CURL_HTTP_VERSION_1_1 ;
239
297
} else {
240
298
$ conf [\CURLOPT_HTTP_VERSION ] = \CURL_HTTP_VERSION_1_0 ;
241
299
}
@@ -455,23 +513,35 @@ private function applyHandlerOptions(EasyHandle $easy, array &$conf): void
455
513
}
456
514
457
515
if (isset ($ options ['crypto_method ' ])) {
458
- if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $ options ['crypto_method ' ]) {
459
- if (!defined ('CURL_SSLVERSION_TLSv1_0 ' )) {
460
- throw new \InvalidArgumentException ('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL ' );
516
+ $ protocolVersion = $ easy ->request ->getProtocolVersion ();
517
+
518
+ // If HTTP/2, upgrade TLS 1.0 and 1.1 to 1.2
519
+ if ('2 ' === $ protocolVersion || '2.0 ' === $ protocolVersion ) {
520
+ if (
521
+ \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $ options ['crypto_method ' ]
522
+ || \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $ options ['crypto_method ' ]
523
+ || \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $ options ['crypto_method ' ]
524
+ ) {
525
+ $ conf [\CURLOPT_SSLVERSION ] = \CURL_SSLVERSION_TLSv1_2;
526
+ } elseif (defined ('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT ' ) && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $ options ['crypto_method ' ]) {
527
+ if (!self ::supportsTls12 ()) {
528
+ throw new \InvalidArgumentException ('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL ' );
529
+ }
530
+ $ conf [\CURLOPT_SSLVERSION ] = \CURL_SSLVERSION_TLSv1_3;
531
+ } else {
532
+ throw new \InvalidArgumentException ('Invalid crypto_method request option: unknown version provided ' );
461
533
}
534
+ } elseif (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $ options ['crypto_method ' ]) {
462
535
$ conf [\CURLOPT_SSLVERSION ] = \CURL_SSLVERSION_TLSv1_0;
463
536
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $ options ['crypto_method ' ]) {
464
- if (!defined ('CURL_SSLVERSION_TLSv1_1 ' )) {
465
- throw new \InvalidArgumentException ('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL ' );
466
- }
467
537
$ conf [\CURLOPT_SSLVERSION ] = \CURL_SSLVERSION_TLSv1_1;
468
538
} elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $ options ['crypto_method ' ]) {
469
- if (!defined ( ' CURL_SSLVERSION_TLSv1_2 ' )) {
539
+ if (!self :: supportsTls12 ( )) {
470
540
throw new \InvalidArgumentException ('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL ' );
471
541
}
472
542
$ conf [\CURLOPT_SSLVERSION ] = \CURL_SSLVERSION_TLSv1_2;
473
543
} elseif (defined ('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT ' ) && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $ options ['crypto_method ' ]) {
474
- if (!defined ( ' CURL_SSLVERSION_TLSv1_3 ' )) {
544
+ if (!self :: supportsTls13 ( )) {
475
545
throw new \InvalidArgumentException ('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL ' );
476
546
}
477
547
$ conf [\CURLOPT_SSLVERSION ] = \CURL_SSLVERSION_TLSv1_3;
0 commit comments