Skip to content

Commit 1c73004

Browse files
async http
1 parent dd7a505 commit 1c73004

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

.editorconfig

Whitespace-only changes.

.gitattributes

Whitespace-only changes.

phpstan.neon.dist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
parameters:
2+
level: max
3+
paths:
4+
- src
5+
autoload_directories:
6+
- src

src/Http/MultiAsyncHandler.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
namespace AsyncHttp\Http;
3+
4+
class MultiAsyncHandler
5+
{
6+
private array $streams = [];
7+
private array $callbacks = [];
8+
9+
public function add(callable $generatorCallback, callable $onDone): void {
10+
$gen = $generatorCallback();
11+
$gen->rewind();
12+
$socket = $this->extractSocket($gen);
13+
if ($socket) {
14+
$this->streams[(int)$socket] = $socket;
15+
$this->callbacks[(int)$socket] = [$gen, $onDone];
16+
}
17+
}
18+
19+
public function run(): void {
20+
while ($this->streams) {
21+
$read = array_values($this->streams);
22+
$write = null; $except = null;
23+
stream_select($read, $write, $except, 5);
24+
25+
foreach ($read as $socket) {
26+
$id = (int)$socket;
27+
[$gen, $callback] = $this->callbacks[$id];
28+
if ($gen->valid()) {
29+
$response = $gen->current();
30+
$callback($response);
31+
unset($this->streams[$id], $this->callbacks[$id]);
32+
}
33+
}
34+
}
35+
}
36+
37+
private function extractSocket(\Generator $gen): mixed {
38+
$r = new \ReflectionObject($gen);
39+
foreach ($r->getProperties() as $prop) {
40+
$prop->setAccessible(true);
41+
$val = $prop->getValue($gen);
42+
if (is_resource($val) && get_resource_type($val) === 'stream') {
43+
return $val;
44+
}
45+
}
46+
return null;
47+
}
48+
}

tests/AsyncHttpClientTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
use PHPUnit\Framework\TestCase;
3+
use AsyncHttp\Http\AsyncHttpClient;
4+
5+
class AsyncHttpClientTest extends TestCase
6+
{
7+
public function testSimpleGetRequest()
8+
{
9+
$client = new AsyncHttpClient();
10+
foreach ($client->get('https://jsonplaceholder.typicode.com/posts/1') as $response) {
11+
$this->assertStringContainsString('userId', $response->getBody());
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)