Skip to content

Commit 6c7d464

Browse files
Respects the $keep_alive param for WebFetchApi::fetch()
Signed-off-by: Jon Stovell <jonstovell@gmail.com>
1 parent 081341d commit 6c7d464

File tree

3 files changed

+64
-11
lines changed

3 files changed

+64
-11
lines changed

Sources/WebFetch/APIs/CurlFetcher.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ class CurlFetcher extends WebFetchApi
122122
*/
123123
public $headers;
124124

125+
/**
126+
* @var bool
127+
*
128+
* Whether to keep the connection open after the initial request.
129+
*/
130+
public bool $keep_alive = false;
131+
125132
/*********************
126133
* Internal properties
127134
*********************/
@@ -192,6 +199,14 @@ public function __construct(array $options = [], int $max_redirect = 3)
192199
$this->max_redirect = max(3, $this->max_redirect);
193200
$this->user_options[CURLOPT_FOLLOWLOCATION] = false;
194201
}
202+
203+
// Do we want to keep the connection open after the initial request?
204+
if (
205+
version_compare(curl_version()['version'], '7.25.0', '>=')
206+
&& !empty($this->user_options[CURLOPT_TCP_KEEPALIVE])
207+
) {
208+
$this->keep_alive = true;
209+
}
195210
}
196211

197212
/**
@@ -243,6 +258,12 @@ public function request(string|Url $url, array|string $post_data = []): object
243258
}
244259

245260
// Set the options and get it.
261+
if (version_compare(curl_version()['version'], '7.25.0', '>=')) {
262+
$this->user_options[CURLOPT_TCP_KEEPALIVE] = (int) $this->keep_alive;
263+
} else {
264+
$this->keep_alive = false;
265+
}
266+
246267
$this->setOptions();
247268
$this->sendRequest(str_replace(' ', '%20', strval($url)));
248269

Sources/WebFetch/APIs/SocketFetcher.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,16 @@ class SocketFetcher extends WebFetchApi
8484
*/
8585
public $response = [];
8686

87-
/*********************
88-
* Internal properties
89-
*********************/
90-
9187
/**
9288
* @var bool
9389
*
9490
* Whether to keep the socket connection open after the initial request.
9591
*/
96-
private bool $keep_alive;
92+
public bool $keep_alive = false;
93+
94+
/*********************
95+
* Internal properties
96+
*********************/
9797

9898
/**
9999
* @var bool

Sources/WebFetch/WebFetchApi.php

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@ abstract class WebFetchApi implements WebFetchApiInterface
6161
'https' => ['SocketFetcher', 'CurlFetcher'],
6262
];
6363

64+
/****************************
65+
* Internal static properties
66+
****************************/
67+
68+
/**
69+
* @var array
70+
*
71+
* Fetchers that still have an open connection after the initial request.
72+
*/
73+
private static array $still_alive = [];
74+
6475
/****************
6576
* Public methods
6677
****************/
@@ -121,14 +132,35 @@ public static function fetch(Url|string $url, string|array $post_data = [], bool
121132
$data = false;
122133
}
123134

124-
foreach (self::$scheme_handlers[$url->scheme] as $class) {
125-
$class = __NAMESPACE__ . '\\APIs\\' . $class;
126-
127-
$fetcher = new $class();
135+
if (isset(self::$still_alive[(string) $url])) {
136+
$fetcher = self::$still_alive[(string) $url];
128137
$fetcher->request($url, $post_data);
138+
} else {
139+
foreach (self::$scheme_handlers[$url->scheme] as $class) {
140+
// Get an instance of the desired class.
141+
$class = __NAMESPACE__ . '\\APIs\\' . $class;
129142

130-
if ($fetcher->result('success')) {
131-
break;
143+
$fetcher = new $class();
144+
145+
// Do we want to keep this connection alive, and can we do so?
146+
if ($keep_alive && property_exists($fetcher, 'keep_alive')) {
147+
$fetcher->keep_alive = $keep_alive;
148+
self::$still_alive[(string) $url] = $fetcher;
149+
}
150+
151+
// Make the request.
152+
$fetcher->request($url, $post_data);
153+
154+
// If keep_alive was turned off during the request, we don't
155+
// need to maintain this instance after we're done the request.
156+
if (!($fetcher->keep_alive ?? false)) {
157+
unset(self::$still_alive[(string) $url]);
158+
}
159+
160+
// If the request worked, we can stop looping.
161+
if ($fetcher->result('success')) {
162+
break;
163+
}
132164
}
133165
}
134166

0 commit comments

Comments
 (0)