Repository navigation
Expand file tree
/
Copy pathdispatcher-sync.php
More file actions
68 lines (59 loc) · 1.98 KB
/
Copy pathdispatcher-sync.php
File metadata and controls
68 lines (59 loc) · 1.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<?php
// Synchronous dispatcher: receive() blocks the thread, so the worker handles one request at a time.
use Rapira\Exception\ClosedException;
use Rapira\Exception\RapiraThrowable;
use Rapira\Http\Request;
final class PageNotFound extends \RuntimeException {}
function handle(Request $req): Generator|string
{
return match ($req->target) {
'/' => "hello from the sync dispatcher\n",
'/echo' => \is_string($req->body) ? $req->body : '',
'/stream' => generateStream(),
'/boom' => throw new \RuntimeException('the handler blew up'),
default => throw new PageNotFound("no route for {$req->target}"),
};
}
function generateStream(): Generator
{
$j = mt_rand(5, 20);
for ($i = 0; $i < $j; $i++) {
yield "stream chunk {$i}\n";
}
return "stream done\n";
}
$d = \Rapira\get_dispatcher();
while (true) {
try {
while (true) {
$ex = $d->receive();
$body = handle($ex->getRequest());
$ex->writeHead(200, ['content-type' => ['text/plain']]);
if ($body instanceof Generator) {
foreach ($body as $chunk) {
$ex->writeBody($chunk, eos: false);
}
$ex->writeBody($body->getReturn());
} else {
$ex->writeBody($body);
}
}
} catch (PageNotFound $e) {
try {
$ex->writeHead(404, ['content-type' => ['text/plain']]);
$ex->writeBody("not found: {$e->getMessage()}\n");
} catch (\Throwable) {
}
} catch (ClosedException) {
// No more work for this app instance: leave the loop.
break;
} catch (RapiraThrowable) {
// The http plugin closed the exchange first - nothing to answer, move on.
} catch (\Throwable $e) {
try {
$ex->writeHead(500, ['content-type' => ['text/plain']]);
$ex->writeBody("internal error: {$e->getMessage()}\n");
} catch (\Throwable) {
}
}
}