Passed
Push — master ( 7becb9...b5be1a )
by Biao
05:04
created

LaravelS::getOutputStyle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Hhxsv5\LaravelS;
4
5
use Hhxsv5\LaravelS\Illuminate\Laravel;
6
use Hhxsv5\LaravelS\Swoole\Coroutine\Context;
7
use Hhxsv5\LaravelS\Swoole\DynamicResponse;
8
use Hhxsv5\LaravelS\Swoole\Request;
9
use Hhxsv5\LaravelS\Swoole\Server;
10
use Hhxsv5\LaravelS\Swoole\StaticResponse;
11
use Hhxsv5\LaravelS\Swoole\Traits\CustomProcessTrait;
12
use Hhxsv5\LaravelS\Swoole\Traits\InotifyTrait;
13
use Hhxsv5\LaravelS\Swoole\Traits\LaravelTrait;
14
use Hhxsv5\LaravelS\Swoole\Traits\LogTrait;
15
use Hhxsv5\LaravelS\Swoole\Traits\ProcessTitleTrait;
16
use Hhxsv5\LaravelS\Swoole\Traits\TimerTrait;
17
use Illuminate\Http\Request as IlluminateRequest;
18
use Symfony\Component\Console\Style\OutputStyle;
19
use Symfony\Component\HttpFoundation\BinaryFileResponse;
20
21
22
/**
23
 * Swoole Request => Laravel Request
24
 * Laravel Request => Laravel handle => Laravel Response
25
 * Laravel Response => Swoole Response
26
 */
27
class LaravelS extends Server
28
{
29
    /**
30
     * Fix conflicts of traits
31
     */
32
    use InotifyTrait, LaravelTrait, LogTrait, ProcessTitleTrait, TimerTrait, CustomProcessTrait {
33
        LogTrait::log insteadof InotifyTrait, TimerTrait, CustomProcessTrait;
34
        LogTrait::logException insteadof InotifyTrait, TimerTrait, CustomProcessTrait;
35
        LogTrait::info insteadof InotifyTrait, TimerTrait, CustomProcessTrait;
36
        LogTrait::warning insteadof InotifyTrait, TimerTrait, CustomProcessTrait;
37
        LogTrait::error insteadof InotifyTrait, TimerTrait, CustomProcessTrait;
38
        LogTrait::callWithCatchException insteadof InotifyTrait, TimerTrait, CustomProcessTrait;
39
        ProcessTitleTrait::setProcessTitle insteadof InotifyTrait, TimerTrait, CustomProcessTrait;
40
        LaravelTrait::initLaravel insteadof TimerTrait, CustomProcessTrait;
41
    }
42
43
    protected $laravelConf;
44
45
    /**
46
     * @var Laravel $laravel
47
     */
48
    protected $laravel;
49
50
    public function __construct(array $svrConf, array $laravelConf)
51
    {
52
        parent::__construct($svrConf);
53
        $this->laravelConf = $laravelConf;
54
55
        $timerCfg = isset($this->conf['timer']) ? $this->conf['timer'] : [];
56
        $timerCfg['process_prefix'] = $svrConf['process_prefix'];
57
        $this->swoole->timerProcess = $this->addTimerProcess($this->swoole, $timerCfg, $this->laravelConf);
0 ignored issues
show
Bug introduced by
The property timerProcess does not seem to exist on swoole_http_server.
Loading history...
Bug introduced by
The property timerProcess does not seem to exist on swoole_websocket_server.
Loading history...
58
59
        $inotifyCfg = isset($this->conf['inotify_reload']) ? $this->conf['inotify_reload'] : [];
60
        if (!isset($inotifyCfg['watch_path'])) {
61
            $inotifyCfg['watch_path'] = $this->laravelConf['root_path'];
62
        }
63
        $inotifyCfg['process_prefix'] = $svrConf['process_prefix'];
64
        $this->swoole->inotifyProcess = $this->addInotifyProcess($this->swoole, $inotifyCfg);
0 ignored issues
show
Bug introduced by
The property inotifyProcess does not seem to exist on swoole_websocket_server.
Loading history...
Bug introduced by
The property inotifyProcess does not seem to exist on swoole_http_server.
Loading history...
65
66
        $processes = isset($this->conf['processes']) ? $this->conf['processes'] : [];
67
        $this->swoole->customProcesses = $this->addCustomProcesses($this->swoole, $svrConf['process_prefix'], $processes, $this->laravelConf);
0 ignored issues
show
Bug introduced by
The property customProcesses does not seem to exist on swoole_websocket_server.
Loading history...
Bug introduced by
The property customProcesses does not seem to exist on swoole_http_server.
Loading history...
68
    }
69
70
    protected function bindWebSocketEvent()
71
    {
72
        parent::bindWebSocketEvent();
73
74
        if ($this->enableWebSocket) {
75
            $eventHandler = function ($method, array $params) {
76
                $this->callWithCatchException(function () use ($method, $params) {
77
                    call_user_func_array([$this->getWebSocketHandler(), $method], $params);
78
                });
79
            };
80
81
            $this->swoole->on('Open', function (\swoole_websocket_server $server, \swoole_http_request $request) use ($eventHandler) {
82
                // Start Laravel's lifetime, then support session ...middleware.
83
                $this->laravel->resetSession();
84
                $laravelRequest = $this->convertRequest($this->laravel, $request);
85
                $this->laravel->bindRequest($laravelRequest);
86
                $this->laravel->handleDynamic($laravelRequest);
87
                $eventHandler('onOpen', func_get_args());
88
                $this->laravel->saveSession();
89
            });
90
        }
91
    }
92
93
    public function onWorkerStart(\swoole_http_server $server, $workerId)
94
    {
95
        parent::onWorkerStart($server, $workerId);
96
97
        // To implement gracefully reload
98
        // Delay to create Laravel
99
        // Delay to include Laravel's autoload.php
100
        $this->laravel = $this->initLaravel($this->laravelConf, $this->swoole);
101
    }
102
103
    protected function convertRequest(Laravel $laravel, \swoole_http_request $request)
104
    {
105
        $rawGlobals = $laravel->getRawGlobals();
106
        $server = isset($rawGlobals['_SERVER']) ? $rawGlobals['_SERVER'] : [];
107
        $env = isset($rawGlobals['_ENV']) ? $rawGlobals['_ENV'] : [];
108
        return (new Request($request))->toIlluminateRequest($server, $env);
109
    }
110
111
    public function onRequest(\swoole_http_request $request, \swoole_http_response $response)
112
    {
113
        parent::onRequest($request, $response);
114
        try {
115
            $laravelRequest = $this->convertRequest($this->laravel, $request);
116
            $this->laravel->bindRequest($laravelRequest);
117
            $this->laravel->fireEvent('laravels.received_request', [$laravelRequest]);
118
            $success = $this->handleStaticResource($this->laravel, $laravelRequest, $response);
119
            if ($success === false) {
120
                $this->handleDynamicResource($this->laravel, $laravelRequest, $response);
121
            }
122
        } catch (\Exception $e) {
123
            $this->handleException($e, $response);
124
        } catch (\Throwable $e) {
125
            $this->handleException($e, $response);
126
        }
127
    }
128
129
    /**
130
     * @param \Exception|\Throwable $e
131
     * @param \swoole_http_response $response
132
     */
133
    protected function handleException($e, \swoole_http_response $response)
134
    {
135
        $error = sprintf(
136
            'onRequest: Uncaught exception "%s"([%d]%s) at %s:%s, %s%s',
137
            get_class($e),
138
            $e->getCode(),
139
            $e->getMessage(),
140
            $e->getFile(),
141
            $e->getLine(),
142
            PHP_EOL,
143
            $e->getTraceAsString()
144
        );
145
        $this->error($error);
146
        try {
147
            $response->status(500);
148
            $response->end('Oops! An unexpected error occurred: ' . $e->getMessage());
149
        } catch (\Exception $e) {
150
            // Catch: zm_deactivate_swoole: Fatal error: Uncaught exception 'ErrorException' with message 'swoole_http_response::status(): http client#2 is not exist.
151
        }
152
    }
153
154
    protected function handleStaticResource(Laravel $laravel, IlluminateRequest $laravelRequest, \swoole_http_response $swooleResponse)
155
    {
156
        // For Swoole < 1.9.17
157
        if (!empty($this->conf['handle_static'])) {
158
            $laravelResponse = $laravel->handleStatic($laravelRequest);
159
            if ($laravelResponse !== false) {
160
                $laravelResponse->headers->set('Server', $this->conf['server'], true);
161
                $laravel->fireEvent('laravels.generated_response', [$laravelRequest, $laravelResponse]);
162
                (new StaticResponse($swooleResponse, $laravelResponse))->send($this->conf['enable_gzip']);
163
                return true;
164
            }
165
        }
166
        return false;
167
    }
168
169
    protected function handleDynamicResource(Laravel $laravel, IlluminateRequest $laravelRequest, \swoole_http_response $swooleResponse)
170
    {
171
        $laravelResponse = $laravel->handleDynamic($laravelRequest);
172
        $laravelResponse->headers->set('Server', $this->conf['server'], true);
173
        $laravel->fireEvent('laravels.generated_response', [$laravelRequest, $laravelResponse]);
174
        $laravel->cleanRequest($laravelRequest);
175
        if ($laravelResponse instanceof BinaryFileResponse) {
176
            (new StaticResponse($swooleResponse, $laravelResponse))->send($this->conf['enable_gzip']);
177
        } else {
178
            (new DynamicResponse($swooleResponse, $laravelResponse))->send($this->conf['enable_gzip']);
179
        }
180
        return true;
181
    }
182
183
    /**
184
     * @var OutputStyle $outputStyle
185
     */
186
    protected static $outputStyle;
187
188
    public static function setOutputStyle(OutputStyle $outputStyle)
189
    {
190
        static::$outputStyle = $outputStyle;
191
    }
192
193
    public static function getOutputStyle()
194
    {
195
        return static::$outputStyle;
196
    }
197
}
198