Completed
Pull Request — master (#109)
by Alex
01:29
created

HttpClient::addTerminationListener()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * High-performance PHP process supervisor and load balancer written in Go
6
 *
7
 * @author Alex Bond
8
 */
9
10
namespace Spiral\RoadRunner;
11
12
use ReflectionFunction;
13
14
class HttpClient
15
{
16
    /** @var Worker */
17
    private $worker;
18
19
    /** @var []callable Array of termination event listeners */
20
    private $terminationListeners = [];
21
22
    /**
23
     * @param Worker $worker
24
     */
25
    public function __construct(Worker $worker)
26
    {
27
        $this->worker = $worker;
28
    }
29
30
    /**
31
     * @return Worker
32
     */
33
    public function getWorker(): Worker
34
    {
35
        return $this->worker;
36
    }
37
38
    /**
39
     * @return array|null Request information as ['ctx'=>[], 'body'=>string] or null if termination request or invalid context.
40
     */
41
    public function acceptRequest()
42
    {
43
        $body = $this->getWorker()->receive($ctx);
44
        if (empty($body) && empty($ctx)) {
45
            // termination request
46
47
            foreach ($this->terminationListeners as $listener) {
48
                call_user_func($listener);
49
            }
50
51
            return null;
52
        }
53
54
        $ctx = json_decode($ctx, true);
55
        if (is_null($ctx)) {
56
            // invalid context
57
            return null;
58
        }
59
60
        return ['ctx' => $ctx, 'body' => $body];
61
    }
62
63
    /**
64
     * Send response to the application server.
65
     *
66
     * @param int        $status  Http status code
67
     * @param string     $body    Body of response
68
     * @param string[][] $headers An associative array of the message's headers. Each
69
     *                            key MUST be a header name, and each value MUST be an array of strings
70
     *                            for that header.
71
     */
72
    public function respond(int $status, string $body, array $headers = [])
73
    {
74
        if (empty($headers)) {
75
            // this is required to represent empty header set as map and not as array
76
            $headers = new \stdClass();
77
        }
78
79
        $this->getWorker()->send(
80
            $body,
81
            json_encode(['status' => $status, 'headers' => $headers])
82
        );
83
    }
84
85
    /**
86
     * Adds function to termination event listeners
87
     *
88
     * @param callable $func Function to call on termination request
89
     * @throws \ReflectionException
90
     */
91
    public function addTerminationListener(callable $func)
92
    {
93
        $f = new ReflectionFunction($func);
94
        if ($f->getNumberOfParameters() > 0) {
95
            throw new \InvalidArgumentException('Termination event callback can\'t have parameters.');
96
        }
97
        $this->terminationListeners[] = $func;
98
    }
99
100
    /**
101
     * Clears all termination event listeners
102
     */
103
    public function clearTerminationListeners()
104
    {
105
        $this->terminationListeners = [];
106
    }
107
}
108