Completed
Push — master ( 10cdf7...b78470 )
by Biao
03:54 queued 42s
created

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