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

136 lines
3.3 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;
2021-03-31 16:52:39 +08:00
use HttpServer\Http\HttpHeaders;
2021-03-19 18:28:59 +08:00
use HttpServer\Http\HttpParams;
2021-03-03 13:44:37 +08:00
use HttpServer\Http\Request;
2021-03-30 19:30:10 +08:00
use HttpServer\Http\Response;
2021-06-25 11:20:38 +08:00
use HttpServer\Route\Router;
2021-04-20 12:12:04 +08:00
use ReflectionException;
2021-08-11 01:04:57 +08:00
use Kiri\Core\ArrayAccess;
use Kiri\Event;
use Kiri\Exception\NotFindClassException;
use Kiri\Kiri;
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
{
2021-06-25 11:20:38 +08:00
/**
* @param $request
* @param $response
* @return Router
* @throws Exception
*/
private function _protocol($request, $response): Router
{
/** @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))) {
throw new Exception('protocol error.', 500);
}
$key = base64_encode(sha1($request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', TRUE));
$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);
}
2021-08-11 01:04:57 +08:00
return Kiri::app()->getRouter();
2021-06-25 11:20:38 +08:00
}
/**
* @param SResponse $response
* @param int $code
* @return void
*/
private function disconnect(SResponse $response, int $code = 500): void
{
2021-08-11 01:04:57 +08:00
$server = Kiri::getWebSocket();
2021-06-25 11:20:38 +08:00
if (!$server->isEstablished($response->fd)) {
return;
}
$response->status($code);
$response->end();
}
/**
* @param SRequest $request
* @param SResponse $response
* @return void
* @throws Exception
*/
public function onHandler(SRequest $request, SResponse $response): void
{
try {
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
$router = $this->_protocol($request, $response);
[$sRequest, $sResponse] = $this->sRequest($request, $response);
if (($node = $router->find_path($sRequest)) !== null) {
$node->dispatch($sRequest, $sResponse);
} else {
$this->disconnect($response, 404);
}
} catch (\Throwable $exception) {
$this->addError($exception, 'throwable');
$response->status(500);
$response->end($exception->getMessage());
}
}
/**
* @param $request
* @param SResponse $response
* @return array
* @throws NotFindClassException
* @throws ReflectionException
* @throws Exception
*/
private function sRequest($request, SResponse $response): array
{
/** @var Request $sRequest */
$sRequest = Request::create($request);
$sRequest->uri = '/' . Socket::HANDSHAKE . '::event';
$sRequest->headers = new HttpHeaders(ArrayAccess::merge($request->server, $request->header));
$sRequest->headers->replace('request_method', 'sw::socket');
$sRequest->headers->replace('request_uri', $sRequest->uri);
$sRequest->params = new HttpParams([], $request->get, []);
$sRequest->parseUri();
return [$sRequest, Response::create($response)];
}
2020-11-10 14:33:55 +08:00
2020-09-02 11:38:47 +08:00
}