Skip to content

Commit 4046b8d

Browse files
ddevsrmichalsn
andauthored
feat: share connection & DNS Cache to CURLRequest (#9557)
* feat: share Connection & DNS Cache to CURLRequest * feat: share connection in CURLRequest * fix: compatible function parameter * docs: fix typo * docs: sample * refactor: revision suggest recommendation * refactor: revision suggest recommendation * Update user_guide_src/source/libraries/curlrequest.rst Co-authored-by: Michal Sniatala <[email protected]> * refactor: more applied suggest recommendation --------- Co-authored-by: Michal Sniatala <[email protected]>
1 parent b014438 commit 4046b8d

File tree

8 files changed

+159
-3
lines changed

8 files changed

+159
-3
lines changed

app/Config/CURLRequest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@
66

77
class CURLRequest extends BaseConfig
88
{
9+
/**
10+
* --------------------------------------------------------------------------
11+
* CURLRequest Share Connection Options
12+
* --------------------------------------------------------------------------
13+
*
14+
* Share connection options between requests.
15+
*
16+
* @var list<int>
17+
*
18+
* @see https://www.php.net/manual/en/curl.constants.php#constant.curl-lock-data-connect
19+
*/
20+
public array $shareConnectionOptions = [
21+
CURL_LOCK_DATA_CONNECT,
22+
CURL_LOCK_DATA_DNS,
23+
];
24+
925
/**
1026
* --------------------------------------------------------------------------
1127
* CURLRequest Share Options

system/HTTP/CURLRequest.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use CodeIgniter\HTTP\Exceptions\HTTPException;
1818
use Config\App;
1919
use Config\CURLRequest as ConfigCURLRequest;
20+
use CurlShareHandle;
2021

2122
/**
2223
* A lightweight HTTP client for sending synchronous HTTP requests via cURL.
@@ -101,6 +102,11 @@ class CURLRequest extends OutgoingRequest
101102
*/
102103
private readonly bool $shareOptions;
103104

105+
/**
106+
* The share connection instance.
107+
*/
108+
protected ?CurlShareHandle $shareConnection = null;
109+
104110
/**
105111
* Takes an array of options to set the following possible class properties:
106112
*
@@ -129,6 +135,20 @@ public function __construct(App $config, URI $uri, ?ResponseInterface $response
129135

130136
$this->config = $this->defaultConfig;
131137
$this->parseOptions($options);
138+
139+
// Share Connection
140+
$optShareConnection = config(ConfigCURLRequest::class)->shareConnectionOptions ?? [
141+
CURL_LOCK_DATA_CONNECT,
142+
CURL_LOCK_DATA_DNS,
143+
];
144+
145+
if ($optShareConnection !== []) {
146+
$this->shareConnection = curl_share_init();
147+
148+
foreach (array_unique($optShareConnection) as $opt) {
149+
curl_share_setopt($this->shareConnection, CURLSHOPT_SHARE, $opt);
150+
}
151+
}
132152
}
133153

134154
/**
@@ -364,7 +384,12 @@ public function send(string $method, string $url)
364384

365385
$curlOptions[CURLOPT_URL] = $url;
366386
$curlOptions[CURLOPT_RETURNTRANSFER] = true;
367-
$curlOptions[CURLOPT_HEADER] = true;
387+
388+
if ($this->shareConnection instanceof CurlShareHandle) {
389+
$curlOptions[CURLOPT_SHARE] = $this->shareConnection;
390+
}
391+
392+
$curlOptions[CURLOPT_HEADER] = true;
368393
// Disable @file uploads in post data.
369394
$curlOptions[CURLOPT_SAFE_UPLOAD] = true;
370395

tests/system/HTTP/CURLRequestShareOptionsTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,18 @@
2828
#[Group('Others')]
2929
final class CURLRequestShareOptionsTest extends CURLRequestTest
3030
{
31-
protected function getRequest(array $options = []): MockCURLRequest
31+
protected function getRequest(array $options = [], ?array $shareConnectionOptions = null): MockCURLRequest
3232
{
3333
$uri = isset($options['baseURI']) ? new URI($options['baseURI']) : new URI();
3434
$app = new App();
3535

3636
$config = new ConfigCURLRequest();
3737
$config->shareOptions = true;
38+
39+
if ($shareConnectionOptions !== null) {
40+
$config->shareConnectionOptions = $shareConnectionOptions;
41+
}
42+
3843
Factories::injectMock('config', 'CURLRequest', $config);
3944

4045
return new MockCURLRequest(($app), $uri, new Response($app), $options);

tests/system/HTTP/CURLRequestTest.php

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Config\App;
2222
use Config\CURLRequest as ConfigCURLRequest;
2323
use CURLFile;
24+
use CurlShareHandle;
2425
use PHPUnit\Framework\Attributes\BackupGlobals;
2526
use PHPUnit\Framework\Attributes\DataProvider;
2627
use PHPUnit\Framework\Attributes\Group;
@@ -45,14 +46,20 @@ protected function setUp(): void
4546

4647
/**
4748
* @param array<string, mixed> $options
49+
* @param array<int, int>|null $shareConnectionOptions
4850
*/
49-
protected function getRequest(array $options = []): MockCURLRequest
51+
protected function getRequest(array $options = [], ?array $shareConnectionOptions = null): MockCURLRequest
5052
{
5153
$uri = isset($options['baseURI']) ? new URI($options['baseURI']) : new URI();
5254
$app = new App();
5355

5456
$config = new ConfigCURLRequest();
5557
$config->shareOptions = false;
58+
59+
if ($shareConnectionOptions !== null) {
60+
$config->shareConnectionOptions = $shareConnectionOptions;
61+
}
62+
5663
Factories::injectMock('config', 'CURLRequest', $config);
5764

5865
return new MockCURLRequest(($app), $uri, new Response($app), $options);
@@ -1235,6 +1242,42 @@ public function testForceResolveIPUnknown(): void
12351242
$this->assertSame(\CURL_IPRESOLVE_WHATEVER, $options[CURLOPT_IPRESOLVE]);
12361243
}
12371244

1245+
public function testShareConnectionDefault(): void
1246+
{
1247+
$this->request->request('GET', 'http://example.com');
1248+
1249+
$options = $this->request->curl_options;
1250+
1251+
$this->assertArrayHasKey(CURLOPT_SHARE, $options);
1252+
$this->assertInstanceOf(CurlShareHandle::class, $options[CURLOPT_SHARE]);
1253+
}
1254+
1255+
public function testShareConnectionEmpty(): void
1256+
{
1257+
$request = $this->getRequest(shareConnectionOptions: []);
1258+
$request->request('GET', 'http://example.com');
1259+
1260+
$options = $request->curl_options;
1261+
1262+
$this->assertArrayNotHasKey(CURLOPT_SHARE, $options);
1263+
}
1264+
1265+
public function testShareConnectionDuplicate(): void
1266+
{
1267+
$request = $this->getRequest(shareConnectionOptions: [
1268+
CURL_LOCK_DATA_CONNECT,
1269+
CURL_LOCK_DATA_DNS,
1270+
CURL_LOCK_DATA_CONNECT,
1271+
CURL_LOCK_DATA_DNS,
1272+
]);
1273+
$request->request('GET', 'http://example.com');
1274+
1275+
$options = $request->curl_options;
1276+
1277+
$this->assertArrayHasKey(CURLOPT_SHARE, $options);
1278+
$this->assertInstanceOf(CurlShareHandle::class, $options[CURLOPT_SHARE]);
1279+
}
1280+
12381281
/**
12391282
* @return iterable<string, array{input: int|string|null, expectedHasKey: bool, expectedValue?: int}>
12401283
*

user_guide_src/source/changelogs/v4.7.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Enhancements
3838
Libraries
3939
=========
4040

41+
- **CURLRequest:** Added ``shareConnection`` config item to change default share connection.
4142
- **CURLRequest:** Added ``dns_cache_timeout`` option to change default DNS cache timeout.
4243
- **CURLRequest:** Added ``fresh_connect`` options to enable/disabled request fresh connection.
4344
- **Email:** Added support for choosing the SMTP authorization method. You can change it via ``Config\Email::$SMTPAuthMethod`` option.

user_guide_src/source/libraries/curlrequest.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,23 @@ to change very little to move over to use Guzzle.
2323
Config for CURLRequest
2424
**********************
2525

26+
.. _curlrequest-sharing-connection:
27+
28+
Sharing Connection
29+
==================
30+
31+
.. versionadded:: 4.7.0
32+
33+
By default, this option is enabled with the constants ``CURL_LOCK_DATA_CONNECT`` and ``CURL_LOCK_DATA_DNS``.
34+
35+
If you want to share connection between requests, set ``$shareConnectionOptions`` with array constant `CURL_LOCK_DATA_* <https://www.php.net/manual/en/curl.constants.php#constant.curl-lock-data-connect>`_ in **app/Config/CURLRequest.php**:
36+
37+
.. literalinclude:: curlrequest/039.php
38+
39+
or when you want to disable it, just change to empty array:
40+
41+
.. literalinclude:: curlrequest/040.php
42+
2643
.. _curlrequest-sharing-options:
2744

2845
Sharing Options
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Config;
4+
5+
use CodeIgniter\Config\BaseConfig;
6+
7+
class CURLRequest extends BaseConfig
8+
{
9+
/**
10+
* --------------------------------------------------------------------------
11+
* CURLRequest Share Connection Options
12+
* --------------------------------------------------------------------------
13+
*
14+
* Share connection options between requests.
15+
*
16+
* @var list<int>
17+
*
18+
* @see https://www.php.net/manual/en/curl.constants.php#constant.curl-lock-data-connect
19+
*/
20+
public array $shareConnection = [
21+
CURL_LOCK_DATA_CONNECT,
22+
CURL_LOCK_DATA_DNS,
23+
];
24+
25+
// ...
26+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Config;
4+
5+
use CodeIgniter\Config\BaseConfig;
6+
7+
class CURLRequest extends BaseConfig
8+
{
9+
/**
10+
* --------------------------------------------------------------------------
11+
* CURLRequest Share Connection Options
12+
* --------------------------------------------------------------------------
13+
*
14+
* Share connection options between requests.
15+
*
16+
* @var list<int>
17+
*
18+
* @see https://www.php.net/manual/en/curl.constants.php#constant.curl-lock-data-connect
19+
*/
20+
public array $shareConnection = [];
21+
22+
// ...
23+
}

0 commit comments

Comments
 (0)