IngressWrapper   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 22
dl 0
loc 80
rs 10
c 0
b 0
f 0
wmc 5

4 Methods

Rating   Name   Duplication   Size   Complexity  
A inbound() 0 10 1
A __construct() 0 4 1
A exception() 0 11 2
A outbound() 0 5 1
1
<?php
2
/**
3
 * Controller invoker
4
 * User: moyo
5
 * Date: 2018/5/29
6
 * Time: 12:15 PM
7
 */
8
9
namespace Carno\Web\Handlers;
10
11
use Carno\Chain\Layered;
12
use function Carno\Coroutine\async;
13
use Carno\Coroutine\Context;
14
use function Carno\Coroutine\race;
15
use function Carno\Coroutine\timeout;
16
use Carno\HTTP\Server\Connection;
17
use Carno\HTTP\Standard\Response;
18
use Carno\HTTP\Standard\ServerRequest;
19
use Carno\Promise\Promised;
20
use Carno\Web\Chips\Server\BodyParser;
21
use Carno\Web\Dispatcher;
22
use Carno\Web\Exception\HTTPException;
23
use Carno\Web\Options;
24
use Throwable;
25
26
class IngressWrapper implements Layered
27
{
28
    use BodyParser;
29
30
    /**
31
     * operated connection
32
     */
33
    public const CONNECTION = 'http-session';
34
35
    /**
36
     * request/response for connection
37
     */
38
    public const REQUESTING = 'http-request';
39
    public const RESPONDING = 'http-response';
40
41
    /**
42
     * @var Dispatcher
43
     */
44
    private $dispatcher = null;
45
46
    /**
47
     * @var Options
48
     */
49
    private $options = null;
50
51
    /**
52
     * IngressWrapper constructor.
53
     * @param Dispatcher $dispatcher
54
     * @param Options $options
55
     */
56
    public function __construct(Dispatcher $dispatcher, Options $options = null)
57
    {
58
        $this->dispatcher = $dispatcher;
59
        $this->options = $options ?? new Options;
60
    }
61
62
    /**
63
     * @param Connection $ingress
64
     * @param Context $ctx
65
     * @return Promised
66
     */
67
    public function inbound($ingress, Context $ctx) : Promised
68
    {
69
        $ctx->set(self::CONNECTION, $ingress);
70
        $ctx->set(self::REQUESTING, $request = $ingress->request());
71
72
        $this->parsedBody($request);
73
74
        return race(async(function (ServerRequest $sr) {
75
            return $this->dispatcher->invoke($sr);
76
        }, $ctx, $request), timeout($this->options->ttExec));
77
    }
78
79
    /**
80
     * @param Response $response
81
     * @param Context $ctx
82
     * @return Response
83
     */
84
    public function outbound($response, Context $ctx) : Response
85
    {
86
        $ctx->set(self::RESPONDING, $response);
87
88
        return $response;
89
    }
90
91
    /**
92
     * @param Throwable $e
93
     * @param Context $ctx
94
     */
95
    public function exception(Throwable $e, Context $ctx) : void
96
    {
97
        if ($e instanceof HTTPException) {
98
            $response = new Response($e->getCode(), [], $e->getMessage());
99
        } else {
100
            $response = new Response(500, [], get_class($e));
101
        }
102
103
        $this->outbound($response, $ctx);
104
105
        throw $e;
106
    }
107
}
108