Skip to content

Commit bfaac06

Browse files
Merge branch '5.0' into 5.1
* 5.0: [Mime] Remove unused var [HttpClient] fix monitoring timeouts when other streams are active [PhpUnitBridge] fix syntax on PHP 5.3 [PhpUnitBridge] Fix undefined index when output of "composer show" cannot be parsed properly cascade validation to child forms [PhpUnitBridge] fix undefined var on version 3.4 Move ajax clear event listener initialization on loadToolbar [HttpClient] Throw JsonException instead of TransportException on empty response in Response::toArray() take into account the context when preserving empty array objects [VarExporter] tfix: s/markAsSkipped/markTestSkipped/ bumped Symfony version to 5.0.10 updated VERSION for 5.0.9 updated CHANGELOG for 5.0.9 bumped Symfony version to 4.4.10 updated VERSION for 4.4.9 updated CHANGELOG for 4.4.9 bumped Symfony version to 3.4.42 updated VERSION for 3.4.41 update CONTRIBUTORS for 3.4.41 updated CHANGELOG for 3.4.41
2 parents 63342ea + e8dde23 commit bfaac06

File tree

7 files changed

+34
-25
lines changed

7 files changed

+34
-25
lines changed

Internal/NativeClientState.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ final class NativeClientState extends ClientState
2828
public $responseCount = 0;
2929
/** @var string[] */
3030
public $dnsCache = [];
31-
/** @var resource[] */
32-
public $handles = [];
3331
/** @var bool */
3432
public $sleep = false;
3533

Response/NativeResponse.php

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,6 @@ private static function schedule(self $response, array &$runningResponses): void
220220
*/
221221
private static function perform(ClientState $multi, array &$responses = null): void
222222
{
223-
// List of native handles for stream_select()
224-
if (null !== $responses) {
225-
$multi->handles = [];
226-
}
227-
228223
foreach ($multi->openHandles as $i => [$h, $buffer, $onProgress]) {
229224
$hasActivity = false;
230225
$remaining = &$multi->openHandles[$i][3];
@@ -291,8 +286,6 @@ private static function perform(ClientState $multi, array &$responses = null): v
291286
$multi->handlesActivity[$i][] = $e;
292287
unset($multi->openHandles[$i]);
293288
$multi->sleep = false;
294-
} elseif (null !== $responses) {
295-
$multi->handles[] = $h;
296289
}
297290
}
298291

@@ -307,7 +300,7 @@ private static function perform(ClientState $multi, array &$responses = null): v
307300
}
308301
}
309302

310-
if (\count($multi->handles) >= $multi->maxHostConnections) {
303+
if (\count($multi->openHandles) >= $multi->maxHostConnections) {
311304
return;
312305
}
313306

@@ -318,10 +311,6 @@ private static function perform(ClientState $multi, array &$responses = null): v
318311
$multi->sleep = false;
319312
self::perform($multi);
320313

321-
if (null !== $response->handle) {
322-
$multi->handles[] = $response->handle;
323-
}
324-
325314
break;
326315
}
327316
}
@@ -335,7 +324,8 @@ private static function perform(ClientState $multi, array &$responses = null): v
335324
private static function select(ClientState $multi, float $timeout): int
336325
{
337326
$_ = [];
327+
$handles = array_column($multi->openHandles, 0);
338328

339-
return (!$multi->sleep = !$multi->sleep) ? -1 : stream_select($multi->handles, $_, $_, (int) $timeout, (int) (1E6 * ($timeout - (int) $timeout)));
329+
return (!$multi->sleep = !$multi->sleep) ? -1 : stream_select($handles, $_, $_, (int) $timeout, (int) (1E6 * ($timeout - (int) $timeout)));
340330
}
341331
}

Response/ResponseTrait.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public function getContent(bool $throw = true): string
137137
public function toArray(bool $throw = true): array
138138
{
139139
if ('' === $content = $this->getContent($throw)) {
140-
throw new TransportException('Response body is empty.');
140+
throw new JsonException('Response body is empty.');
141141
}
142142

143143
if (null !== $this->jsonData) {
@@ -316,7 +316,7 @@ public static function stream(iterable $responses, float $timeout = null): \Gene
316316
}
317317

318318
$lastActivity = microtime(true);
319-
$isTimeout = false;
319+
$enlapsedTimeout = 0;
320320

321321
while (true) {
322322
$hasActivity = false;
@@ -338,15 +338,15 @@ public static function stream(iterable $responses, float $timeout = null): \Gene
338338
} elseif (!isset($multi->openHandles[$j])) {
339339
unset($responses[$j]);
340340
continue;
341-
} elseif ($isTimeout) {
341+
} elseif ($enlapsedTimeout >= $timeoutMax) {
342342
$multi->handlesActivity[$j] = [new ErrorChunk($response->offset, sprintf('Idle timeout reached for "%s".', $response->getInfo('url')))];
343343
} else {
344344
continue;
345345
}
346346

347347
while ($multi->handlesActivity[$j] ?? false) {
348348
$hasActivity = true;
349-
$isTimeout = false;
349+
$enlapsedTimeout = 0;
350350

351351
if (\is_string($chunk = array_shift($multi->handlesActivity[$j]))) {
352352
if (null !== $response->inflate && false === $chunk = @inflate_add($response->inflate, $chunk)) {
@@ -379,7 +379,7 @@ public static function stream(iterable $responses, float $timeout = null): \Gene
379379
}
380380
} elseif ($chunk instanceof ErrorChunk) {
381381
unset($responses[$j]);
382-
$isTimeout = true;
382+
$enlapsedTimeout = $timeoutMax;
383383
} elseif ($chunk instanceof FirstChunk) {
384384
if ($response->logger) {
385385
$info = $response->getInfo();
@@ -447,10 +447,11 @@ public static function stream(iterable $responses, float $timeout = null): \Gene
447447
continue;
448448
}
449449

450-
switch (self::select($multi, $timeoutMin)) {
451-
case -1: usleep(min(500, 1E6 * $timeoutMin)); break;
452-
case 0: $isTimeout = microtime(true) - $lastActivity > $timeoutMax; break;
450+
if (-1 === self::select($multi, min($timeoutMin, $timeoutMax - $enlapsedTimeout))) {
451+
usleep(min(500, 1E6 * $timeoutMin));
453452
}
453+
454+
$enlapsedTimeout = microtime(true) - $lastActivity;
454455
}
455456
}
456457
}

Tests/CurlHttpClientTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,13 @@ protected function getHttpClient(string $testCase): HttpClientInterface
3333

3434
return new CurlHttpClient(['verify_peer' => false, 'verify_host' => false]);
3535
}
36+
37+
public function testTimeoutIsNotAFatalError()
38+
{
39+
if ('\\' === \DIRECTORY_SEPARATOR) {
40+
$this->markTestSkipped('Too transient on Windows');
41+
}
42+
43+
parent::testTimeoutIsNotAFatalError();
44+
}
3645
}

Tests/HttpClientTestCase.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,17 @@ public function testToStream404()
8383
$this->assertSame($response, stream_get_meta_data($stream)['wrapper_data']->getResponse());
8484
$this->assertSame(404, $response->getStatusCode());
8585

86-
$this->expectException(ClientException::class);
8786
$response = $client->request('GET', 'http://localhost:8057/404');
88-
$stream = $response->toStream();
87+
$this->expectException(ClientException::class);
88+
$response->toStream();
8989
}
9090

9191
public function testNonBlockingStream()
9292
{
9393
$client = $this->getHttpClient(__FUNCTION__);
9494
$response = $client->request('GET', 'http://localhost:8057/timeout-body');
9595
$stream = $response->toStream();
96+
usleep(10000);
9697

9798
$this->assertTrue(stream_set_blocking($stream, false));
9899
$this->assertSame('<1>', fread($stream, 8192));

Tests/MockHttpClientTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ protected function getHttpClient(string $testCase): HttpClientInterface
190190
$this->markTestSkipped("MockHttpClient doesn't unzip");
191191
break;
192192

193+
case 'testTimeoutWithActiveConcurrentStream':
194+
$this->markTestSkipped('Real transport required');
195+
break;
196+
193197
case 'testDestruct':
194198
$this->markTestSkipped("MockHttpClient doesn't timeout on destruct");
195199
break;

Tests/Response/MockResponseTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ public function testToArrayError($content, $responseHeaders, $message)
3535

3636
public function toArrayErrors()
3737
{
38+
yield [
39+
'content' => '',
40+
'responseHeaders' => [],
41+
'message' => 'Response body is empty.',
42+
];
43+
3844
yield [
3945
'content' => '{}',
4046
'responseHeaders' => ['content-type' => 'plain/text'],

0 commit comments

Comments
 (0)