Issues (24)

src/Dispatcher.php (1 issue)

1
<?php
2
/**
3
 * Web dispatcher
4
 * User: moyo
5
 * Date: 2018/5/29
6
 * Time: 12:12 PM
7
 */
8
9
namespace Carno\Web;
10
11
use function Carno\Coroutine\ctx;
12
use Carno\HTTP\Standard\Response;
13
use Carno\HTTP\Standard\ServerRequest;
14
use Carno\Web\Chips\Dispatcher\Executor;
15
use Carno\Web\Chips\Dispatcher\Policing;
16
use Carno\Web\Chips\Dispatcher\Responsive;
17
use Carno\Web\Exception\InternalServerException;
18
use Carno\Web\Exception\MethodNotAllowedException;
19
use Carno\Web\Exception\RouterNotFoundException;
20
use FastRoute\Dispatcher as FRDispatcher;
21
use Throwable;
22
23
class Dispatcher
24
{
25
    use Policing, Executor, Responsive;
26
27
    /**
28
     * @var FRDispatcher
29
     */
30
    private $router = null;
31
32
    /**
33
     * @param FRDispatcher $dispatcher
34
     */
35
    public function dispatched(FRDispatcher $dispatcher) : void
36
    {
37
        $this->router = $dispatcher;
38
    }
39
40
    /**
41
     * @param ServerRequest $sr
42
     * @return Response
43
     * @throws Throwable
44
     */
45
    public function invoke(ServerRequest $sr)
46
    {
47
        $routed = $this->router->dispatch($sr->getMethod(), $sr->getUri()->getPath());
48
49
        $ctx = yield ctx();
0 ignored issues
show
Bug Best Practice introduced by
The expression yield ctx() returns the type Generator which is incompatible with the documented return type Carno\HTTP\Standard\Response.
Loading history...
50
51
        if ($this->policy
52
            && $response = $this->policy->request(
53
                $ctx,
54
                $sr,
55
                $routed[0],
56
                $routed[0] === FRDispatcher::FOUND ? $routed[1] : null,
57
                $routed[0] === FRDispatcher::FOUND ? $routed[2] : []
58
            )
59
        ) {
60
            return $response;
61
        }
62
63
        switch ($routed[0]) {
64
            case FRDispatcher::FOUND:
65
                $respond = $this->responding(
66
                    $sr,
67
                    ...(yield $this->calling($ctx, $sr, $routed[1], $routed[2]))
68
                );
69
                return $this->policy ? $this->policy->response($sr, $respond) : $respond;
70
            case FRDispatcher::NOT_FOUND:
71
                throw new RouterNotFoundException;
72
            case FRDispatcher::METHOD_NOT_ALLOWED:
73
                throw new MethodNotAllowedException;
74
            default:
75
                throw new InternalServerException('Routing failed');
76
        }
77
    }
78
}
79