Files
kiri-core/HttpServer/Events/OnHandshake.php
T

125 lines
2.8 KiB
PHP
Raw Normal View History

2020-09-02 11:38:47 +08:00
<?php
2020-10-29 18:17:25 +08:00
declare(strict_types=1);
2020-09-02 11:38:47 +08:00
namespace HttpServer\Events;
2020-12-15 14:04:02 +08:00
use Annotation\Route\Socket;
2020-09-02 11:38:47 +08:00
use Exception;
2020-09-04 01:05:33 +08:00
use HttpServer\Abstracts\Callback;
2020-11-10 14:33:55 +08:00
use Snowflake\Event;
use Snowflake\Exception\ComponentException;
2020-09-02 11:38:47 +08:00
use Snowflake\Snowflake;
2020-11-27 14:52:04 +08:00
use Swoole\Coroutine;
2020-09-02 11:38:47 +08:00
use Swoole\Http\Request as SRequest;
use Swoole\Http\Response as SResponse;
use Swoole\WebSocket\Server;
/**
* Class OnHandshake
* @package HttpServer\Events
*/
class OnHandshake extends Callback
{
/**
2020-11-10 14:33:55 +08:00
* @param $request
* @param $response
2020-09-02 11:38:47 +08:00
* @throws Exception
*/
2020-11-10 14:33:55 +08:00
private function resolveParse($request, $response)
2020-09-02 11:38:47 +08:00
{
/** @var Server $server */
$secWebSocketKey = $request->header['sec-websocket-key'];
$patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
2020-11-10 14:33:55 +08:00
throw new Exception('protocol error.', 500);
2020-09-02 11:38:47 +08:00
}
2021-02-08 16:52:27 +08:00
$key = base64_encode(sha1($request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', TRUE));
2020-09-02 11:38:47 +08:00
$headers = [
'Upgrade' => 'websocket',
'Connection' => 'Upgrade',
'Sec-websocket-Accept' => $key,
'Sec-websocket-Version' => '13',
];
if (isset($request->header['sec-websocket-protocol'])) {
$headers['Sec-websocket-Protocol'] = $request->header['sec-websocket-protocol'];
}
foreach ($headers as $key => $val) {
$response->header($key, $val);
}
2020-11-10 14:33:55 +08:00
}
/**
* @param $response
* @param int $code
* @return false
*/
2020-12-17 14:09:14 +08:00
private function disconnect($response, $code = 500): bool
2020-11-10 14:33:55 +08:00
{
$response->status($code);
$response->end();
return false;
}
2021-02-08 16:52:27 +08:00
/**
* @param $response
* @param int $code
* @return false
*/
private function connect($response, $code = 101): bool
{
$response->status($code);
$response->end();
return false;
}
2020-11-10 14:33:55 +08:00
/**
* @param SRequest $request
* @param SResponse $response
2020-12-17 14:09:14 +08:00
* @return void
2021-02-08 16:52:27 +08:00
* @throws Exception
2020-11-10 14:33:55 +08:00
*/
2020-12-17 14:09:14 +08:00
public function onHandler(SRequest $request, SResponse $response): void
2020-11-27 14:57:58 +08:00
{
Coroutine::defer(function () {
fire(Event::EVENT_AFTER_REQUEST);
});
$this->execute($request, $response);
}
/**
* @param SRequest $request
* @param SResponse $response
2020-12-15 14:04:02 +08:00
* @return mixed
* @throws Exception
2020-11-27 14:57:58 +08:00
*/
2020-12-15 14:04:02 +08:00
private function execute(SRequest $request, SResponse $response): mixed
2020-11-10 14:33:55 +08:00
{
try {
$this->resolveParse($request, $response);
2021-01-08 11:12:32 +08:00
if (isset($request->get['debug']) && $request->get['debug'] == 'test') {
2021-02-08 16:52:27 +08:00
return $this->connect($response, 101);
2021-01-08 11:12:32 +08:00
}
2020-12-15 14:04:02 +08:00
$router = Snowflake::app()->getRouter();
2020-12-15 17:14:02 +08:00
$node = $router->search('/' . Socket::HANDSHAKE . '::event', 'sw::socket');
2020-12-15 14:04:02 +08:00
if ($node === null) {
return $this->disconnect($response, 502);
2020-11-10 14:33:55 +08:00
}
2020-12-15 17:26:07 +08:00
return $node->dispatch($request, $response);
2020-11-10 14:33:55 +08:00
} catch (\Throwable $exception) {
2020-12-15 17:30:33 +08:00
$this->addError($exception->getMessage() . ' ' . $exception->getFile() . ' ' . $exception->getLine());
2020-11-10 14:33:55 +08:00
return $this->disconnect($response, 500);
2020-09-02 11:38:47 +08:00
}
2020-11-10 14:33:55 +08:00
}
2020-09-02 11:38:47 +08:00
}