This commit is contained in:
2020-09-04 00:41:33 +08:00
parent 622071256e
commit 46f9de1f6a
141 changed files with 105 additions and 73 deletions
-13
View File
@@ -1,13 +0,0 @@
<?php
namespace HttpServer\Abstracts;
use Swoole\Coroutine;
abstract class BaseContext
{
protected static $pool = [];
}
-133
View File
@@ -1,133 +0,0 @@
<?php
namespace HttpServer\Events\Abstracts;
use Exception;
use HttpServer\Application;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use Snowflake\Config;
use Snowflake\Error\Logger;
use Snowflake\Event;
use Snowflake\Exception\ConfigException;
use Snowflake\Snowflake;
use Swoole\Timer;
abstract class Callback extends Application
{
/**
* @param $server
* @param $worker_id
* @param $message
* @throws Exception
*/
protected function clear($server, $worker_id, $message)
{
Timer::clearAll();
$event = Snowflake::app()->event;
$event->offName(Event::EVENT_AFTER_REQUEST);
$event->offName(Event::EVENT_BEFORE_REQUEST);
$this->eventNotify($message, $event);
Snowflake::clearProcessId($server->worker_pid);
$logger = Snowflake::app()->getLogger();
$logger->write($this->_MESSAGE[$message] . $worker_id);
$logger->clear();
}
const EVENT_ERROR = 'WORKER:ERROR';
const EVENT_STOP = 'WORKER:STOP';
const EVENT_EXIT = 'WORKER:EXIT';
private $_MESSAGE = [
self::EVENT_ERROR => 'The server error. at No.',
self::EVENT_STOP => 'The server stop. at No.',
self::EVENT_EXIT => 'The server exit. at No.',
];
/**
* @param $message
* @param $event
*/
private function eventNotify($message, $event)
{
switch ($message) {
case self::EVENT_ERROR:
if (!$event->exists(Event::SERVER_WORKER_ERROR)) {
return;
}
$event->trigger(Event::SERVER_WORKER_ERROR);
break;
case self::EVENT_EXIT:
if (!$event->exists(Event::SERVER_WORKER_EXIT)) {
return;
}
$event->trigger(Event::SERVER_WORKER_EXIT);
break;
case self::EVENT_STOP:
if (!$event->exists(Event::SERVER_WORKER_STOP)) {
return;
}
$event->trigger(Event::SERVER_WORKER_STOP);
break;
}
}
/**
* @return PHPMailer
* @throws \PHPMailer\PHPMailer\Exception
* @throws ConfigException
*/
private function createEmail()
{
$mail = new PHPMailer(true);
$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = Config::get('email.host'); // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Debugoutput = false; // Enable SMTP authentication
$mail->CharSet = "UTF8"; // Enable SMTP authentication
$mail->Username = Config::get('email.username'); // SMTP username
$mail->Password = Config::get('email.password'); // SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$mail->Port = Config::get('email.port'); // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
$mail->setFrom(Config::get('email.send.address'), Config::get('email.send.nickname'));
return $mail;
}
/**
* @param $message
* @throws
*/
protected function system_mail($message)
{
try {
$mail = $this->createEmail();
$receives = Config::get('email.receive');
if (empty($receives) || !is_array($receives)) {
throw new Exception('接收人信息错误');
}
foreach ($receives as $receive) {
$mail->addAddress($receive['address'], $receive['nickname']); // Add a recipient
}
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'service error';
$mail->Body = $message;
$mail->AltBody = $message;
$mail->send();
} catch (Exception $e) {
$this->addError($e->getMessage(), 'email');
}
}
}
-14
View File
@@ -1,14 +0,0 @@
<?php
namespace HttpServer\Abstracts;
use Snowflake\Abstracts\Component;
abstract class HttpService extends Component
{
}
-41
View File
@@ -1,41 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/11/8 0008
* Time: 18:37
*/
namespace HttpServer\Abstracts;
use HttpServer\Application;
use Swoole\WebSocket\Server;
/**
* Class ServerBase
* @package Snowflake\Snowflake\Server
*/
abstract class ServerBase extends Application
{
/** @var Server */
protected $server;
/**
* @return Server
*/
public function getServer()
{
return $this->server;
}
/**
* @param $server
*/
public function setServer($server)
{
$this->server = $server;
}
}
-51
View File
@@ -1,51 +0,0 @@
<?php
namespace HttpServer;
use Exception;
use HttpServer\Abstracts\HttpService;
use Snowflake\Snowflake;
/**
* Class Application
* @package HttpServer
*/
class Application extends HttpService
{
/**
* @param $message
* @param string $category
* @throws Exception
*/
protected function write($message, $category = 'app')
{
$logger = Snowflake::app()->logger;
$logger->write($message, $category);
$logger->insert();
}
/**
* @param $methods
* @return mixed
* @throws Exception
*/
public function __get($methods)
{
if (method_exists($this, $methods)) {
return $this->{$methods}();
}
$handler = 'get' . ucfirst($methods);
if (method_exists($this, $handler)) {
return $this->{$handler}();
}
if (property_exists($this, $methods)) {
return $this->$methods;
}
$message = sprintf('method %s::%s not exists.', get_called_class(), $methods);
throw new Exception($message);
}
}
File diff suppressed because it is too large Load Diff
-187
View File
@@ -1,187 +0,0 @@
<?php
namespace HttpServer\Client;
use HttpServer\Application;
use Exception;
/**
* Class Result
*
* @package app\components
*
* @property $code
* @property $message
* @property $count
* @property $data
*/
class Result extends Application
{
public $code;
public $message;
public $count = 0;
public $data;
public $header;
public $httpStatus = 200;
public $startTime = 0;
public $requestTime = 0;
public $runTime = 0;
public $statusCode = [100, 101, 200, 201, 202, 203, 204, 205, 206];
/**
* Result constructor.
* @param array $data
* @param array $config
*/
public function __construct(array $data, $config = [])
{
parent::__construct($config);
foreach ($data as $key => $val) {
$this->$key = $val;
}
}
/**
* @param $name
* @return mixed|null
*/
public function __get($name)
{
return $this->$name;
}
/**
* @param $name
* @param $value
* @return $this|void
*/
public function __set($name, $value)
{
$this->$name = $value;
return $this;
}
/**
* @return array
*/
public function getHeaders()
{
$_tmp = [];
if (!is_array($this->header)) {
return $_tmp;
}
foreach ($this->header as $key => $val) {
if ($key == 0) {
$_tmp['pro'] = $val;
} else {
$trim = explode(': ', $val);
$_tmp[strtolower($trim[0])] = $trim[1];
}
}
return $_tmp;
}
/**
* @return array
*/
public function getTime()
{
return [
'startTime' => $this->startTime,
'requestTime' => $this->requestTime,
'runTime' => $this->runTime,
];
}
/**
* @param $key
* @param $data
* @return $this
* @throws Exception
*/
public function setAttr($key, $data)
{
if (!property_exists($this, $key)) {
throw new Exception('未查找到相应对象属性');
}
$this->$key = $data;
return $this;
}
/**
* @param int $status
* @return bool
*/
public function isResultsOK($status = 0)
{
if (!$this->httpIsOk()) {
return false;
}
return $this->code === $status;
}
/**
* @return bool
*/
public function httpIsOk()
{
return in_array($this->httpStatus, $this->statusCode);
}
/**
* @return mixed
*/
public function getResponse()
{
$headers = $this->getHeaders();
if (!isset($headers['content-type'])) {
return $this->data;
}
if (!is_string($this->data)) {
return $this->data;
}
switch (trim($headers['content-type'])) {
case 'application/json; encoding=utf-8';
case 'application/json;';
case 'application/json';
case 'text/plain';
return json_decode($this->data, true);
break;
}
return $this->data;
}
/**
* @param $key
* @param $data
* @return $this
*/
public function append($key, $data)
{
$this->data[$key] = $data;
return $this;
}
/**
* @return mixed
*/
public function getMessage()
{
return $this->message;
}
/**
* @return mixed
*/
public function getCode()
{
return $this->code;
}
}
-42
View File
@@ -1,42 +0,0 @@
<?php
namespace HttpServer;
use Console\Dtl;
use Snowflake\Exception\ComponentException;
use Snowflake\Snowflake;
/**
* Class Command
* @package HttpServer
*/
class Command extends \Console\Command
{
public $command = 'server';
public $description = 'server start|stop|reload|restart';
private $actions = [
'start', 'stop', 'reload', 'restart'
];
/**
* @param Dtl $dtl
* @throws ComponentException
*/
public function handler(Dtl $dtl)
{
$action = $dtl->get('action', 3);
/** @var Server $server */
$server = Snowflake::app()->get('server');
$server->start();
}
}
-105
View File
@@ -1,105 +0,0 @@
<?php
namespace HttpServer;
use HttpServer\Http\HttpHeaders;
use HttpServer\Http\HttpParams;
use HttpServer\Http\Request;
use Exception;
use Snowflake\Snowflake;
/**
* Class WebController
* @package Snowflake\Snowflake\Web
*/
class Controller extends Application
{
/** @var HttpParams $input */
public $input;
/** @var HttpHeaders */
public $headers;
/** @var Request */
public $request;
/**
* @param HttpParams $input
*/
public function setInput(HttpParams $input): void
{
$this->input = $input;
}
/**
* @param HttpHeaders $headers
*/
public function setHeaders(HttpHeaders $headers): void
{
$this->headers = $headers;
}
/**
* @param Request $request
*/
public function setRequest(Request $request): void
{
$this->request = $request;
}
/**
* @return HttpParams
* @throws Exception
*/
public function getInput(): HttpParams
{
if (!$this->input) {
$this->input = $this->getRequest()->params;
}
return $this->input;
}
/**
* @return HttpHeaders
* @throws Exception
*/
public function getHeaders(): HttpHeaders
{
if (!$this->headers) {
$this->headers = $this->getRequest()->headers;
}
return $this->headers;
}
/**
* @return Request
* @throws Exception
*/
public function getRequest(): Request
{
if (!$this->request) {
$this->request = Snowflake::app()->request;
}
return $this->request;
}
/**
* @param $name
* @return mixed|null
* @throws Exception
*/
public function __get($name)
{
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->$method();
}
return parent::__get($name);
}
}
-36
View File
@@ -1,36 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnAfterReload
* @package HttpServer\Events
*/
class OnAfterReload extends Callback
{
/**
* @param Server $server
* @throws ComponentException
* @throws Exception
*/
public function onHandler(Server $server)
{
$event = Snowflake::app()->getEvent();
if (!$event->exists(Event::SERVER_AFTER_RELOAD)) {
return;
}
$event->trigger(Event::SERVER_AFTER_RELOAD, [$server]);
}
}
-33
View File
@@ -1,33 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnBeforeReload
* @package HttpServer\Events
*/
class OnBeforeReload extends Callback
{
/**
* @param Server $server
* @throws Exception
*/
public function onHandler(Server $server)
{
$event = Snowflake::app()->getEvent();
if (!$event->exists(Event::SERVER_BEFORE_RELOAD)) {
return;
}
$event->trigger(Event::SERVER_BEFORE_RELOAD, [$server]);
}
}
-75
View File
@@ -1,75 +0,0 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Route\Annotation\Annotation;
use HttpServer\Route\Annotation\Tcp;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
use Exception;
use Swoole\Http\Server as HServer;
use Swoole\WebSocket\Server as WServer;
/**
* Class OnClose
* @package HttpServer\Events
*/
class OnClose extends Callback
{
/**
* @param Server $server
* @param int $fd
* @throws Exception
*/
public function onHandler(Server $server, int $fd)
{
try {
[$manager, $name] = $this->resovle($server, $fd);
if ($manager !== null && !$manager->has($name)) {
$manager->runWith($name, [$fd]);
}
} catch (\Throwable $exception) {
$this->addError($exception->getMessage());
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::RELEASE_ALL);
$logger = Snowflake::app()->getLogger();
$logger->insert();
}
}
/**
* @param $server
* @param $fd
* @return array|null
* @throws Exception
*/
public function resovle($server, $fd)
{
if ($server instanceof WServer) {
if (!$server->isEstablished($fd)) {
return [null, null];
}
$manager = Snowflake::app()->annotation->get('websocket');
$name = $manager->getName(AWebsocket::CLOSE);
} else if ($server instanceof HServer) {
$manager = Snowflake::app()->annotation->get('http');
$name = $manager->getName(Annotation::CLOSE);
} else {
$manager = Snowflake::app()->annotation->get('tcp');
$name = $manager->getName(Tcp::CLOSE);
}
return [$manager, $name];
}
}
-38
View File
@@ -1,38 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnConnect
* @package HttpServer\Events
*/
class OnConnect extends Callback
{
/**
* @param Server $server
* @param int $fd
* @param int $reactorId
* @throws Exception
*/
public function onHandler(\Swoole\Server $server, int $fd, int $reactorId)
{
$event = Snowflake::app()->event;
if (!$event->exists(Event::RECEIVE_CONNECTION)) {
return;
}
$event->trigger(Event::RECEIVE_CONNECTION, [$server, $fd, $reactorId]);
}
}
-26
View File
@@ -1,26 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Swoole\Server;
class OnFinish extends Callback
{
/**
* @param Server $server
* @param $task_id
* @param $data
* @throws Exception
*/
public function onHandler(Server $server, $task_id, $data)
{
$data = json_decode($data, true);
$data['work_id'] = $task_id;
$this->write(var_export($data, true), 'Task');
}
}
-67
View File
@@ -1,67 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use Snowflake\Snowflake;
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
{
/**
* @param SRequest $request
* @param SResponse $response
* @return bool|string
* @throws Exception
*/
public function onHandler(SRequest $request, SResponse $response)
{
/** @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))) {
return false;
}
$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);
}
/** @var AWebsocket $manager */
$manager = Snowflake::app()->annotation->get('websocket');
if ($manager->has($manager->getName(AWebsocket::HANDSHAKE))) {
$manager->runWith($manager->getName(AWebsocket::HANDSHAKE), [$request, $response]);
} else {
$response->status(502);
$response->end();
}
return true;
}
}
-33
View File
@@ -1,33 +0,0 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
class OnManagerStart extends Callback
{
/**
* @param Server $server
* @throws \Exception
*/
public function onHandler(Server $server)
{
$this->debug('manager start.');
Snowflake::setProcessId($server->manager_pid);
$events = Snowflake::app()->event;
if ($events->exists(Event::SERVER_MANAGER_START)) {
$events->trigger(Event::SERVER_MANAGER_START, null, $server);
}
if (Snowflake::isLinux()) {
name('Server Manager.');
}
}
}
-41
View File
@@ -1,41 +0,0 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnManagerStop
* @package HttpServer\Events
*/
class OnManagerStop extends Callback
{
/**
* @param $server
* @throws \Exception
*/
public function onHandler(Server $server)
{
$this->warning('manager stop.');
$events = Snowflake::app()->event;
if ($events->exists(Event::SERVER_MANAGER_STOP)) {
$events->trigger(Event::SERVER_MANAGER_STOP, [$server]);
}
// $runPath = storage(null, 'workerIds');
// foreach (glob($runPath . '/*') as $item) {
// if (!file_exists($item)) {
// continue;
// }
// @unlink($item);
// }
}
}
-57
View File
@@ -1,57 +0,0 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
/**
* Class OnMessage
* @package HttpServer\Events
*/
class OnMessage extends Callback
{
/**
* @param Server $server
* @param Frame $frame
* @throws
*/
public function onHandler(Server $server, Frame $frame)
{
try {
if ($frame->opcode == 0x08) {
return;
}
$event = Snowflake::app()->event;
if ($event->exists(Event::SERVER_MESSAGE)) {
$event->trigger(Event::SERVER_MESSAGE, [$server, $frame]);
} else {
$frame->data = json_decode($frame->data, true);
}
/** @var AWebsocket $manager */
$manager = Snowflake::app()->annotation->get('websocket');
if (!isset($frame->data['route'])) {
throw new \Exception('Fromat errr.');
}
$events = $manager->getName(AWebsocket::MESSAGE, [null, null, $frame->data['route']]);
$manager->runWith($events, [$frame, $server]);
} catch (\Exception $exception) {
$this->addError($exception->getMessage(), 'websocket');
$server->send($frame->fd, $exception->getMessage());
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::EVENT_AFTER_REQUEST);
Snowflake::app()->logger->insert();
}
}
}
-87
View File
@@ -1,87 +0,0 @@
<?php
namespace HttpServer\Events;
use Closure;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Core\JSON;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
use Exception;
/**
* Class OnPacket
* @package HttpServer\Events
*/
class OnPacket extends Callback
{
/** @var Closure|array */
public $unpack;
/** @var Closure|array */
public $pack;
/**
* @param $data
* @return mixed
* @throws Exception
*/
public function pack($data)
{
$callback = $this->pack;
if (is_callable($callback, true)) {
return $callback($data);
}
return JSON::encode($data);
}
/**
* @param $data
* @return mixed
*/
public function unpack($data)
{
$callback = $this->unpack;
if (is_callable($callback, true)) {
return $callback($data);
}
return JSON::decode($data);
}
/**
* @param Server $server
* @param $data
* @param $clientInfo
* @return mixed
* @throws
*/
public function onHandler($server, $data, $clientInfo)
{
try {
$client = [$clientInfo['address'], $clientInfo['port']];
if (empty($data = $this->unpack($data))) {
throw new Exception('Format error.');
}
$client[] = $this->pack($data);
return $server->sendto(...$client);
} catch (\Throwable $exception) {
$client[] = $this->pack(['message' => $exception->getMessage()]);
return $server->sendto(...$client);
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::SERVER_WORKER_STOP);
}
}
}
-38
View File
@@ -1,38 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnPipeMessage
* @package HttpServer\Events
*/
class OnPipeMessage extends Callback
{
/**
* @param Server $server
* @param int $src_worker_id
* @param $message
* @throws ComponentException
* @throws Exception
*/
public function onHandler(Server $server, int $src_worker_id, $message)
{
// TODO: Implement onHandler() method.
$events = Snowflake::app()->getEvent();
if (!$events->exists(Event::PIPE_MESSAGE)) {
return;
}
$events->trigger(Event::PIPE_MESSAGE, [$server, $src_worker_id, $message]);
}
}
-86
View File
@@ -1,86 +0,0 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Core\JSON;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
use Exception;
use Closure;
/**
* Class OnReceive
* @package HttpServer\Events
*/
class OnReceive extends Callback
{
/** @var Closure|array */
public $unpack;
/** @var Closure|array */
public $pack;
/**
* @param $data
* @return mixed
* @throws Exception
*/
public function pack($data)
{
$callback = $this->pack;
if (is_callable($callback, true)) {
return $callback($data);
}
return JSON::encode($data);
}
/**
* @param $data
* @return mixed
*/
public function unpack($data)
{
$callback = $this->unpack;
if (is_callable($callback, true)) {
return $callback($data);
}
return JSON::decode($data);
}
/**
* @param Server $server
* @param int $fd
* @param int $reactorId
* @param string $data
* @return mixed
* @throws Exception
*/
public function onHandler(\Swoole\Server $server, int $fd, int $reactorId, string $data)
{
try {
$client = [$fd];
if (empty($data = $this->unpack($data))) {
throw new Exception('Format error.');
}
$client[] = $this->pack($data);
return $server->send(...$client);
} catch (\Throwable $exception) {
$client[] = $this->pack(['message' => $exception->getMessage()]);
return $server->send(...$client);
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::SERVER_WORKER_STOP);
}
}
}
-116
View File
@@ -1,116 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Http\Context;
use HttpServer\Http\Request as HRequest;
use HttpServer\Http\Response as HResponse;
use HttpServer\Service\Http;
use Snowflake\Core\JSON;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Error;
use Swoole\Http\Request;
use Swoole\Http\Response;
/**
* Class OnRequest
* @package HttpServer\Events
*/
class OnRequest extends Callback
{
/**
* @param Request $request
* @param Response $response
* @return void
* @throws Exception
*/
public function onHandler(Request $request, Response $response)
{
try {
/** @var HRequest $sRequest */
[$sRequest, $sResponse] = static::setContext($request, $response);
if ($sRequest->is('favicon.ico')) {
return $sResponse->send($sRequest->isNotFound(), 200);
}
$sResponse->send(Snowflake::app()->router->dispatch(), 200);
} catch (Error | \Throwable $exception) {
$this->sendErrorMessage($sResponse ?? null, $exception, $response);
} finally {
$events = Snowflake::app()->getEvent();
if (!$events->exists(Event::EVENT_AFTER_REQUEST)) {
return;
}
$events->trigger(Event::EVENT_AFTER_REQUEST, [$request]);
}
}
/**
* @param $sResponse
* @param $exception
* @param $response
* @throws Exception
*/
protected function sendErrorMessage($sResponse, $exception, $response)
{
if (empty($sResponse)) {
$response->status(200);
$response->end($exception->getMessage());
} else {
$sResponse->send($this->format($exception), 200);
}
}
/**
* @param Exception $exception
* @return false|int|mixed|string
* @throws Exception
*/
public function format($exception)
{
$errorInfo = [
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
'line' => $exception->getLine()
];
$this->error(var_export($errorInfo, true));
$code = $exception->getCode() ?? 500;
$logger = Snowflake::app()->logger;
$string = 'Exception: ' . PHP_EOL;
$string .= '#. message: ' . $errorInfo['message'] . PHP_EOL;
$string .= '#. file: ' . $errorInfo['file'] . PHP_EOL;
$string .= '#. line: ' . $errorInfo['line'] . PHP_EOL;
$logger->write($string . $exception->getTraceAsString(), 'trace');
$logger->write(jTraceEx($exception), 'exception');
return JSON::to($code, $errorInfo['message']);
}
/**
* @param $request
* @param $response
* @return array
* @throws Exception
*/
public static function setContext($request, $response): array
{
$request = Context::setContext('request', HRequest::create($request));
$response = Context::setContext('response', HResponse::create($response));
return [$request, $response];
}
}
-43
View File
@@ -1,43 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use Snowflake\Config;
use Snowflake\Core\JSON;
use Snowflake\Error\Logger;
use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Exception\ConfigException;
use Snowflake\Snowflake;
use Swoole\Server;
use Closure;
/**
* Class OnShutdown
* @package HttpServer\Events
*/
class OnShutdown extends Callback
{
/**
* @param Server $server
* @throws ComponentException
* @throws Exception
*/
public function onHandler(Server $server)
{
$this->system_mail('server shutdown~');
$event = Snowflake::app()->getEvent();
if (!$event->exists(Event::SERVER_SHUTDOWN)) {
return;
}
$event->trigger(Event::SERVER_SHUTDOWN);
}
}
-30
View File
@@ -1,30 +0,0 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
class OnStart extends Callback
{
/**
* @param Server $server
* @throws \Exception
*/
public function onHandler($server)
{
$time = storage('socket.sock');
Snowflake::writeFile($time, $server->master_pid);
$event = Snowflake::app()->event;
if ($event->exists(Event::SERVER_EVENT_START)) {
$event->trigger(Event::SERVER_EVENT_START, null, $server);
}
}
}
-142
View File
@@ -1,142 +0,0 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\IInterface\Task as ITask;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
use Swoole\Timer;
use Exception;
/**
* Class OnTask
* @package HttpServer\Events
*/
class OnTask extends Callback
{
/**
* @throws Exception
*/
public function onHandler()
{
$parameter = func_get_args();
if (func_num_args() < 4) {
$this->onContinueTask(...$parameter);
} else {
$this->onTask(...$parameter);
}
}
/**
* @param Server $server
* @param int $task_id
* @param int $from_id
* @param string $data
*
* @return mixed|void
* @throws Exception
* 异步任务
*/
public function onTask(Server $server, $task_id, $from_id, $data)
{
$time = microtime(TRUE);
if (empty($data)) {
return $server->finish('null data');
}
$finish = $this->runTaskHandler($data);
if (!$finish) {
$finish = [];
}
$finish['runTime'] = [
'startTime' => $time,
'runTime' => microtime(TRUE) - $time,
'endTime' => microtime(TRUE),
];
$server->finish(json_encode($finish));
}
/**
* @param Server $server
* @param Server\Task $task
* @return mixed|void
* @throws Exception
* 异步任务
*/
public function onContinueTask(Server $server, Server\Task $task)
{
$time = microtime(TRUE);
if (empty($task->data)) {
return $task->finish('null data');
}
$finish = $this->runTaskHandler($task->data);
if (!$finish) {
$finish = [];
}
$finish['runTime'] = [
'startTime' => $time,
'runTime' => microtime(TRUE) - $time,
'endTime' => microtime(TRUE),
];
$task->finish(json_encode($finish));
}
/**
* @param $data
* @return array|null
* @throws Exception
*/
private function runTaskHandler($data)
{
$serialize = $this->before($data);
try {
$params = $serialize->getParams();
if (is_object($params)) {
$params = get_object_vars($params);
}
$finish['class'] = get_class($serialize);
$finish['params'] = $params;
$finish['status'] = 'success';
$finish['info'] = $serialize->handler();
} catch (\Throwable $exception) {
$finish['status'] = 'error';
$finish['info'] = $this->format($exception);
$this->error($exception, 'Task');
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::RELEASE_ALL);
Timer::clearAll();
}
return $finish;
}
/**
* @param $data
* @return ITask|null
*/
protected function before($data)
{
if (empty($serialize = unserialize($data))) {
return null;
}
if (!($serialize instanceof ITask)) {
return null;
}
return $serialize;
}
/**
* @param $exception
* @return string
*/
private function format($exception)
{
return $exception->getMessage() . " on line " . $exception->getLine() . " at file " . $exception->getFile();
}
}
-38
View File
@@ -1,38 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Config;
use Snowflake\Exception\ConfigException;
use Swoole\Server;
class OnWorkerError extends Callback
{
/**
* @param Server $server
* @param int $worker_id
* @param int $worker_pid
* @param int $exit_code
* @param int $signal
* @throws Exception
*/
public function onHandler(Server $server, int $worker_id, int $worker_pid, int $exit_code, int $signal)
{
$this->clear($server, $worker_id, self::EVENT_ERROR);
if (!Config::has('email')) {
return;
}
$this->system_mail(print_r([
'$worker_pid' => $worker_pid,
'$worker_id' => $worker_id,
'$exit_code' => $exit_code,
'$signal' => $signal,
], true));
}
}
-27
View File
@@ -1,27 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
/**
* Class OnWorkerExit
* @package HttpServer\Events
*/
class OnWorkerExit extends Callback
{
/**
* @param $server
* @param $worker_id
* @throws Exception
*/
public function onHandler($server, $worker_id)
{
$this->clear($server, $worker_id, self::EVENT_EXIT);
}
}
-81
View File
@@ -1,81 +0,0 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use HttpServer\Service\Http;
use HttpServer\Service\Websocket;
use Snowflake\Error\Logger;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnWorkerStart
* @package HttpServer\Events
*/
class OnWorkerStart extends Callback
{
/**
* @param Server $server
* @param int $worker_id
*
* @return mixed|void
* @throws Exception
*/
public function onHandler(Server $server, $worker_id)
{
Snowflake::setProcessId($server->worker_pid);
$get_name = $this->get_process_name($server, $worker_id);
if (!empty($get_name) && !Snowflake::isMac()) {
swoole_set_process_name($get_name);
}
if ($worker_id >= $server->setting['worker_num']) {
return;
}
$this->setWorkerAction($server, $worker_id);
}
/**
* @param $worker_id
* @param $socket
* @throws Exception
*/
private function setWorkerAction($socket, $worker_id)
{
try {
$this->debug(sprintf('Worker #%d is start.....', $worker_id));
$event = Snowflake::app()->event;
if (!$event->exists(Event::SERVER_WORKER_START)) {
return;
}
$event->trigger(Event::SERVER_WORKER_START);
} catch (\Throwable $exception) {
Snowflake::app()->getLogger()->write($exception->getMessage(), 'worker');
}
}
/**
* @param $socket
* @param $worker_id
* @return string
*/
private function get_process_name($socket, $worker_id)
{
$prefix = 'system:';
if ($worker_id >= $socket->setting['worker_num']) {
return $prefix . ': Task: No.' . $worker_id;
} else {
return $prefix . ': worker: No.' . $worker_id;
}
}
}
-23
View File
@@ -1,23 +0,0 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
class OnWorkerStop extends Callback
{
/**
* @param $server
* @param $worker_id
* @throws \Exception
*/
public function onHandler($server, $worker_id)
{
$this->clear($server, $worker_id, self::EVENT_STOP);
}
}
-26
View File
@@ -1,26 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/5/25 0025
* Time: 10:14
*/
namespace HttpServer\Exception;
use Throwable;
/**
* Class AuthException
* @package Snowflake\Snowflake\Exception
*/
class AuthException extends \Exception
{
public function __construct($message = "", $code = 0, Throwable $previous = NULL)
{
parent::__construct($message, 7000, $previous);
}
}
@@ -1,10 +0,0 @@
<?php
namespace HttpServer\Exception;
class RequestException extends \Exception
{
}
-196
View File
@@ -1,196 +0,0 @@
<?php
namespace HttpServer\Http;
use HttpServer\Abstracts\BaseContext;
use Swoole\Coroutine;
/**
* Class Context
* @package Yoc\http
*/
class Context extends BaseContext
{
protected static $_requests = [];
protected static $_response = [];
/**
* @param $id
* @param $context
* @param null $key
* @return mixed
*/
public static function setContext($id, $context, $key = null)
{
if (static::inCoroutine()) {
return self::setCoroutine($id, $context, $key);
} else {
return self::setStatic($id, $context, $key);
}
}
/**
* @param $id
* @param $context
* @param null $key
* @return mixed
*/
private static function setStatic($id, $context, $key = null)
{
if (!empty($key)) {
if (!is_array(static::$_requests[$id])) {
static::$_requests[$id] = [$key => $context];
} else {
static::$_requests[$id][$key] = $context;
}
} else {
static::$_requests[$id] = $context;
}
return $context;
}
/**
* @param $id
* @param $context
* @param null $key
* @return
*/
private static function setCoroutine($id, $context, $key = null)
{
if (!static::hasContext($id)) {
Coroutine::getContext()[$id] = [];
}
if (!empty($key)) {
if (!is_array(Coroutine::getContext()[$id])) {
Coroutine::getContext()[$id] = [$key => $context];
} else {
Coroutine::getContext()[$id][$key] = $context;
}
} else {
Coroutine::getContext()[$id] = $context;
}
return $context;
}
/**
* @param $id
* @param null $key
* @return false|mixed
*/
public static function autoIncr($id, $key = null)
{
if (!static::inCoroutine()) {
return false;
}
if (!isset(Coroutine::getContext()[$id][$key])) {
return false;
}
return Coroutine::getContext()[$id][$key] += 1;
}
/**
* @param $id
* @param null $key
* @return false|mixed
*/
public static function autoDecr($id, $key = null)
{
if (!static::inCoroutine()) {
return false;
}
if (!isset(Coroutine::getContext()[$id][$key])) {
return false;
}
return Coroutine::getContext()[$id][$key] -= 1;
}
/**
* @param $id
* @param null $key
* @return mixed
*/
public static function getContext($id, $key = null)
{
if (static::inCoroutine()) {
$array = Coroutine::getContext()[$id] ?? null;
} else {
$array = static::$_requests[$id] ?? null;
}
if (empty($key) || !is_array($array)) {
return $array;
}
return $array[$key];
}
/**
* @return mixed
*/
public static function getAllContext()
{
if (static::inCoroutine()) {
return Coroutine::getContext() ?? [];
} else {
return static::$_requests ?? [];
}
}
/**
* @param $id
* @param null $key
*/
public static function deleteId($id, $key = null)
{
if (!static::hasContext($id, $key)) {
return;
}
if (static::inCoroutine()) {
if (!empty($key)) {
Coroutine::getContext()[$id][$key] = null;
} else {
Coroutine::getContext()[$id] = null;
}
} else {
unset(static::$_requests[$id]);
}
}
/**
* @param $id
* @param null $key
* @return mixed
*/
public static function hasContext($id, $key = null)
{
if (static::inCoroutine()) {
$data = Coroutine::getContext()[$id] ?? null;
} else {
$data = static::$_requests[$id] ?? null;
}
if (empty($data)) {
return false;
}
if (empty($key)) {
return true;
} else if (!is_array($data)) {
return false;
}
return isset($data[$key]);
}
/**
* @return bool
*/
public static function inCoroutine()
{
return Coroutine::getCid() > 0;
}
}
-94
View File
@@ -1,94 +0,0 @@
<?php
namespace HttpServer\Http;
use Exception;
use Snowflake\Snowflake;
/**
* Class File
*/
class File
{
public $name = '';
public $tmp_name = '';
public $error = '';
public $type = '';
public $size = '';
private $newName = '';
private $errorInfo = [
0 => 'UPLOAD_ERR_OK.',
1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini.',
2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
3 => 'The uploaded file was only partially uploaded.',
4 => 'No file was uploaded.',
6 => 'Missing a temporary folder.',
7 => 'Failed to write file to disk.',
8 => 'A PHP extension stopped the file upload.'
];
/**
* @param string $path
* @return bool
* @throws Exception
*/
public function saveTo(string $path)
{
if ($this->hasError()) {
throw new Exception($this->getErrorInfo());
}
@move_uploaded_file($this->tmp_name, $path);
if (!file_exists($path)) {
return false;
}
return true;
}
/**
* @return string
*/
public function rename()
{
if (!empty($this->newName)) {
return $this->newName;
}
$param = ['tmp_name' => $this->getTmpPath()];
$this->newName = Snowflake::rename($param);
return $this->newName;
}
/**
* @return string
*/
public function getTmpPath()
{
return $this->tmp_name;
}
/**
* @return bool
*
* check file have error
*/
public function hasError()
{
return $this->error !== 0;
}
/**
* @return mixed
*
* get upload error info
*/
public function getErrorInfo()
{
if (!isset($this->errorInfo[$this->error])) {
return 'Unknown upload error.';
}
return $this->errorInfo[$this->error];
}
}
@@ -1,59 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/8 0008
* Time: 17:51
*/
namespace HttpServer\Http\Formatter;
use Snowflake\Core\JSON;
use HttpServer\Application;
use Swoole\Http\Response;
use HttpServer\IInterface\IFormatter;
/**
* Class HtmlFormatter
* @package Snowflake\Snowflake\Http\Formatter
*/
class HtmlFormatter extends Application implements IFormatter
{
public $data;
/** @var Response */
public $status;
public $header = [];
/**
* @param $data
* @return $this
* @throws \Exception
*/
public function send($data)
{
if (!is_string($data)) {
$data = JSON::encode($data);
}
$this->data = $data;
return $this;
}
/**
* @return mixed
*/
public function getData()
{
$data = $this->data;
$this->clear();
return $data;
}
public function clear()
{
unset($this->data);
}
}
@@ -1,56 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/8 0008
* Time: 17:18
*/
namespace HttpServer\Http\Formatter;
use Exception;
use HttpServer\Application;
use HttpServer\IInterface\IFormatter;
/**
* Class JsonFormatter
* @package Snowflake\Snowflake\Http\Formatter
*/
class JsonFormatter extends Application implements IFormatter
{
public $data;
public $status = 200;
public $header = [];
/**
* @param $data
* @return $this|IFormatter
* @throws Exception
*/
public function send($data)
{
if (!is_string($data)) {
$data = json_encode($data);
}
$this->data = $data;
return $this;
}
/**
* @return mixed
*/
public function getData()
{
$data = $this->data;
$this->clear();
return $data;
}
public function clear()
{
unset($this->data);
}
}
@@ -1,87 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/8 0008
* Time: 17:29
*/
namespace HttpServer\Http\Formatter;
use HttpServer\Application;
use SimpleXMLElement;
use Swoole\Http\Response;
use HttpServer\IInterface\IFormatter;
/**
* Class XmlFormatter
* @package Snowflake\Snowflake\Http\Formatter
*/
class XmlFormatter extends Application implements IFormatter
{
public $data = '';
/** @var Response */
public $status;
public $header = [];
/**
* @param $data
* @return $this
* @throws \Exception
*/
public function send($data)
{
if (!is_string($data)) {
// TODO: Implement send() method.
$dom = new SimpleXMLElement('<xml/>');
$this->toXml($dom, $data);
$this->data = $dom->saveXML();
}
return $this;
}
/**
* @return string
*/
public function getData()
{
$data = $this->data;
$this->clear();
return $data;
}
/**
* @param SimpleXMLElement $dom
* @param $data
*/
public function toXml($dom, $data)
{
foreach ($data as $key => $val) {
if (is_numeric($key)) {
$key = 'item' . $key;
}
if (is_array($val)) {
$node = $dom->addChild($key);
$this->toXml($node, $val);
} else if (is_object($val)) {
$val = get_object_vars($val);
$node = $dom->addChild($key);
$this->toXml($node, $val);
} else {
$dom->addChild($key, htmlspecialchars($val));
}
}
}
public function clear()
{
unset($this->data);
}
}
-144
View File
@@ -1,144 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-18
* Time: 14:54
*/
namespace HttpServer\Http;
/**
* Class HttpHeaders
* @package Snowflake\Snowflake\Http
*/
class HttpHeaders
{
/**
* @var string[]
*/
private $headers = [];
/**
* @var string[]
*/
private $response = [];
/**
* HttpHeaders constructor.
* @param $headers
*/
public function __construct($headers)
{
$this->headers = $headers;
}
/**
* @param $name
* @param $value
*/
public function setHeader($name, $value)
{
$this->response[$name] = $value;
}
/**
* @param array $headers
*/
public function setHeaders(array $headers)
{
foreach ($headers as $key => $val) {
$this->response[$key] = $val;
}
}
/**
* @param $name
* @param $value
*/
public function replace($name, $value)
{
$this->headers[$name] = $value;
}
/**
* @param $name
* @param $value
*/
public function addHeader($name, $value)
{
$this->headers[$name] = $value;
}
/**
* @param array $headers
* @return $this
*/
public function addHeaders(array $headers)
{
if (empty($headers)) {
return $this;
}
if (!empty($this->headers)) {
$headers = array_merge($this->headers, $headers);
}
$this->headers = $headers;
return $this;
}
/**
* @return array
*/
public function getResponseHeaders()
{
return $this->response;
}
/**
* @return array
*/
public function toArray()
{
return $this->headers;
}
/**
* @param $name
* @return mixed|null
*/
public function getHeader($name)
{
return $this->headers[$name] ?? null;
}
/**
* @param $name
* @return mixed|string|null
*/
public function get($name)
{
return $this->getHeader($name);
}
/**
* @param $name
* @return bool
*/
public function exists($name)
{
return isset($this->headers[$name]) && $this->headers[$name] != null;
}
/**
* @return array
*/
public function getHeaders()
{
return $this->headers;
}
}
-404
View File
@@ -1,404 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-18
* Time: 14:54
*/
namespace HttpServer\Http;
use Exception;
use HttpServer\Exception\RequestException;
use Snowflake\Snowflake;
/**
* Class HttpParams
* @package Snowflake\Snowflake\Http
*/
class HttpParams
{
/** @var array */
private $body = [];
/** @var array */
private $gets = [];
/** @var array */
private $files = [];
/**
* HttpParams constructor.
* @param $body
* @param $get
* @param $files
*/
public function __construct($body, $get, $files)
{
$this->body = $body;
$this->gets = $get ?? [];
$this->files = $files ?? [];
}
/**
* @return int
*/
public function offset()
{
return ($this->page() - 1) * $this->size();
}
/**
* @param array $data
* 批量添加数据
*/
public function setPosts($data)
{
if (!is_array($data)) {
return;
}
foreach ($data as $key => $vla) {
$this->body[$key] = $vla;
}
}
/**
* @param string $key
* @param string $value
*/
public function addGetParam(string $key, string $value)
{
$this->gets[$key] = $value;
}
/**
* @return int
*/
private function page()
{
return (int)$this->get('page', 1);
}
/**
* @return int
*/
public function size()
{
return (int)$this->get('size', 20);
}
/**
* @param $name
* @param $defaultValue
* @param $call
* @return mixed|null
*/
public function get($name, $defaultValue = null, $call = null)
{
return $this->gets[$name] ?? $defaultValue;
}
/**
* @param $name
* @param null $defaultValue
* @param $call
* @return mixed|null
*/
public function post($name, $defaultValue = null, $call = null)
{
$data = $this->body[$name] ?? $defaultValue;
if ($call !== null) {
$data = call_user_func($call, $data);
}
return $data;
}
/**
* @param $name
* @return false|string
* @throws Exception
*/
public function json($name)
{
$data = $this->array($name);
if (empty($data)) {
return JSON::encode([]);
} else if (!is_array($data)) {
return JSON::encode([]);
}
return JSON::encode($data);
}
/**
* @return array
*/
public function gets()
{
return $this->gets;
}
/**
* @return array
*/
public function params()
{
return array_merge($this->body ?? [], $this->files ?? []);
}
/**
* @return array
*/
public function load()
{
return array_merge($this->files, $this->body, $this->gets);
}
/**
* @param $name
* @param array $defaultValue
* @return array|mixed
*/
public function array($name, $defaultValue = [])
{
return $this->body[$name] ?? $defaultValue;
}
/**
* @param $name
* @return mixed|File|null
* @throws Exception
*/
public function file($name)
{
if (!isset($this->files[$name])) {
return null;
}
$param = $this->files[$name];
$param['class'] = File::class;
return Snowflake::createObject($param);
}
/**
* @param $name
* @param bool $isNeed
* @return mixed|null
* @throws RequestException
*/
private function required($name, $isNeed = false)
{
$int = $this->body[$name] ?? NULL;
if (is_null($int) && $isNeed === true) {
throw new RequestException("You need to add request parameter $name");
}
return $int;
}
/**
* @param $name
* @param bool $isNeed
* @param null $min
* @param null $max
* @return int
* @throws Exception
*/
public function int($name, $isNeed = FALSE, $min = NULL, $max = NULL)
{
$int = $this->required($name, $isNeed);
if ($int === null) return null;
if (is_array($min)) {
list($min, $max) = $min;
}
if (is_null($int)) {
$length = 0;
} else {
$length = strlen(floatval($int));
}
if (!is_numeric($int) || intval($int) != $int) {
throw new RequestException("The request parameter $name must integer.");
}
$this->between($length, $min, $max);
return (int)$int;
}
/**
* @param $name
* @param bool $isNeed
* @param int $round
* @return float
* @throws Exception
*/
public function float($name, $isNeed = FALSE, $round = 0)
{
$int = $this->required($name, $isNeed);
if ($int === null) {
return null;
}
if ($round > 0) {
return round(floatval($int), $round);
} else {
return floatval($int);
}
}
/**
* @param $name
* @param bool $isNeed
* @param null $length
*
* @return string
* @throws
*/
public function string($name, $isNeed = FALSE, $length = NULL)
{
$string = $this->required($name, $isNeed);
if ($string === null || $length === null) {
return $string;
}
if (!is_string($string)) {
$string = json_encode($string, JSON_UNESCAPED_UNICODE);
}
$_length = strlen($string);
if (is_array($length)) {
if (count($length) < 2) {
array_unshift($length, 0);
}
$this->between($_length, ...$length);
} else if (is_numeric($length) && $_length != $length) {
throw new RequestException("The length of the string must be $length characters");
}
return $string;
}
/**
* @param $_length
* @param $min
* @param $max
* @throws RequestException
*/
private function between($_length, $min, $max)
{
if ($min !== NULL && $_length < $min) {
throw new RequestException("The minimum value cannot be lower than $min");
}
if ($max !== NULL && $_length > $max) {
throw new RequestException("Maximum cannot exceed $max, has length " . $_length);
}
}
/**
* @param $name
* @param bool $isNeed
*
* @return string
* @throws RequestException
*/
public function email($name, $isNeed = FALSE)
{
$email = $this->required($name, $isNeed);
if ($email === null) {
return null;
}
if (!preg_match('/^\w+([.-_]\w+)+@\w+(\.\w+)+$/', $email)) {
throw new RequestException("Request parameter $name is in the wrong format", 4001);
}
return $email;
}
/**
* @param $name
* @param bool $isNeed
*
* @return string
* @throws RequestException
*/
public function bool($name, $isNeed = FALSE)
{
$email = $this->required($name, $isNeed);
if ($email === null) {
return false;
}
return (bool)$email;
}
/**
* @param $name
* @param null $default
*
* @return mixed|null
* @throws RequestException
*/
public function timestamp($name, $default = NULL)
{
$value = $this->required($name, false);
if ($value === null) {
return $default;
}
if (!is_numeric($value)) {
throw new RequestException('The request param :attribute not is a timestamp value');
}
if (strlen((string)$value) != 10) {
throw new RequestException('The request param :attribute not is a timestamp value');
}
if (!date('YmdHis', $value)) {
throw new RequestException('The request param :attribute format error', 4001);
}
return $value;
}
/**
* @param $name
* @param null $default
*
* @return mixed|null
* @throws RequestException
*/
public function datetime($name, $default = NULL)
{
$value = $this->required($name, false);
if ($value === null) {
return $default;
}
$match = '/^\d{4}.*?([1-12]).*([1-31]).*?[0-23].*?[0-59].*?[0-59].*?$/';
$match = preg_match($match, $value, $result);
if (!$match || $result[0] != $value) {
throw new RequestException('The request param :attribute format error', 4001);
}
return $value;
}
/**
* @param $name
* @param null $default
* @return mixed|null
* @throws RequestException
*/
public function ip($name, $default = NULL)
{
$value = $this->required($name, false);
if ($value == NULL) {
return $default;
}
$match = preg_match('/^\d{1,3}(\.\d{1,3}){3}$/', $value, $result);
if (!$match || $result[0] != $value) {
throw new RequestException('The request param :attribute format error', 4001);
}
return $value;
}
/**
* @param $name
* @return mixed|null
*/
public function __get($name)
{
$load = $this->load();
return $load[$name] ?? null;
}
}
-438
View File
@@ -1,438 +0,0 @@
<?php
namespace HttpServer\Http;
use Snowflake\Core\Help;
use Exception;
use HttpServer\Application;
use HttpServer\IInterface\AuthIdentity;
use Snowflake\Core\JSON;
use Snowflake\Snowflake;
defined('REQUEST_OK') or define('REQUEST_OK', 0);
defined('REQUEST_FAIL') or define('REQUEST_FAIL', 500);
/**
* Class HttpRequest
*
* @package Snowflake\Snowflake\HttpRequest
*
* @property-read $isPost
* @property-read $isGet
* @property-read $isOption
* @property-read $isDelete
* @property-read $isHttp
* @property-read $method
* @property-read $identity
* @property-read $isPackage
* @property-read $isReceive
*/
class Request extends Application
{
/** @var int $fd */
public $fd = 0;
/** @var HttpParams */
public $params;
/** @var HttpHeaders */
public $headers;
/** @var bool */
public $isCli = FALSE;
/** @var float */
public $startTime;
public $uri = '';
public $statusCode = 200;
/** @var string[] */
private $explode = [];
const PLATFORM_MAC_OX = 'mac';
const PLATFORM_IPHONE = 'iphone';
const PLATFORM_ANDROID = 'android';
const PLATFORM_WINDOWS = 'windows';
/**
* @var AuthIdentity|null
*/
private $_grant = null;
/**
* @param $fd
*/
public function setFd($fd)
{
$this->fd = $fd;
}
/**
* @return bool
*/
public function isFavicon()
{
return $this->getUri() === 'favicon.ico';
}
/**
* @return mixed
*/
public function getIdentity()
{
return $this->_grant;
}
/**
* @return bool
*/
public function isHead()
{
$result = $this->headers->getHeader('request_method') == 'head';
if ($result) {
$this->setStatus(101);
} else {
$this->setStatus(200);
}
return $result;
}
/**
* @param $status
* @return mixed
*/
public function setStatus($status)
{
return $this->statusCode = $status;
}
/**
* @return int
*/
public function getStatus()
{
return $this->statusCode;
}
/**
* @return bool
*/
public function getIsPackage()
{
return $this->headers->getHeader('request_method') == 'package';
}
/**
* @return bool
*/
public function getIsReceive()
{
return $this->headers->getHeader('request_method') == 'receive';
}
/**
* @param $value
*/
public function setGrantAuthorization($value)
{
$this->_grant = $value;
}
/**
* @return bool
*/
public function hasGrant()
{
return $this->_grant !== null;
}
/**
* @return string
*/
public function parseUri()
{
$array = [];
$explode = explode('/', $this->headers->getHeader('request_uri'));
foreach ($explode as $item) {
if (empty($item)) {
continue;
}
$array[] = $item;
}
return $this->uri = implode('/', ($this->explode = $array));
}
/**
* @return string[]
*/
public function getExplode()
{
return $this->explode;
}
/**
* @return mixed|string
*/
public function getCurrent()
{
return current($this->explode);
}
/**
* @return string
*/
public function getUri()
{
if (!$this->headers) {
return 'command exec.';
}
if (!empty($this->uri)) {
return $this->uri;
}
$uri = $this->headers->getHeader('request_uri');
$uri = ltrim($uri, '/');
if (empty($uri)) return '/';
return $uri;
}
/**
* @return mixed|string
* @throws Exception
*/
public function adapter()
{
if (!$this->isHead()) {
return router()->runHandler();
}
return '';
}
/**
* @return string|null
*/
public function getPlatform()
{
$user = $this->headers->getHeader('user-agent');
$match = preg_match('/\(.*\)?/', $user, $output);
if (!$match || count($output) < 1) {
return null;
}
$output = strtolower(array_shift($output));
if (strpos('mac', $output)) {
return 'mac';
} else if (strpos('iphone', $output)) {
return 'iphone';
} else if (strpos('android', $output)) {
return 'android';
} else if (strpos('windows', $output)) {
return 'windows';
}
return null;
}
/**
* @return bool
*/
public function isIos()
{
return $this->getPlatform() == static::PLATFORM_IPHONE;
}
/**
* @return bool
*/
public function isAndroid()
{
return $this->getPlatform() == static::PLATFORM_ANDROID;
}
/**
* @return bool
*/
public function isMacOs()
{
return $this->getPlatform() == static::PLATFORM_MAC_OX;
}
/**
* @return bool
*/
public function isWindows()
{
return $this->getPlatform() == static::PLATFORM_WINDOWS;
}
/**
* @return bool
*/
public function getIsPost()
{
return $this->getMethod() == 'post';
}
/**
* @return bool
* @throws Exception
*/
public function getIsHttp()
{
return true;
}
/**
* @return bool
*/
public function getIsOption()
{
return $this->getMethod() == 'options';
}
/**
* @return bool
*/
public function getIsGet()
{
return $this->getMethod() == 'get';
}
/**
* @return bool
*/
public function getIsDelete()
{
return $this->getMethod() == 'delete';
}
/**
* @return string
*
* 获取请求类型
*/
public function getMethod()
{
$head = $this->headers->getHeader('request_method');
return strtolower($head);
}
/**
* @return bool
*/
public function getIsCli()
{
return $this->isCli === TRUE;
}
/**
* @param $name
* @param $value
*
* @throws Exception
*/
public function __set($name, $value)
{
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
$this->$method($value);
} else {
parent::__set($name, $value); // TODO: Change the autogenerated stub
}
}
/**
* @return mixed|null
*/
public function getIp()
{
$headers = $this->headers->getHeaders();
if (!empty($headers['x-forwarded-for'])) return $headers['x-forwarded-for'];
if (!empty($headers['request-ip'])) return $headers['request-ip'];
if (!empty($headers['remote_addr'])) return $headers['remote_addr'];
return NULL;
}
/**
* @return string
*/
public function getRuntime()
{
return sprintf('%.5f', microtime(TRUE) - $this->startTime);
}
/**
* @return string
*/
public function getDebug()
{
$mainstay = sprintf("%.6f", microtime(true)); // 带毫秒的时间戳
$timestamp = floor($mainstay); // 时间戳
$milliseconds = round(($mainstay - $timestamp) * 1000); // 毫秒
$datetime = date("Y-m-d H:i:s", $timestamp) . '.' . $milliseconds;
$tmp = [
'[Debug ' . $datetime . '] ',
$this->getIp(),
$this->getUri(),
'`' . $this->headers->getHeader('user-agent') . '`',
$this->getRuntime()
];
return implode(' ', $tmp);
}
/**
* @param $router
* @return bool
*/
public function is($router)
{
return $this->getUri() == trim($router, '/');
}
/**
* @param $router
* @return bool
*/
public function isNotFound()
{
return JSON::to(404, 'Page ' . $this->getUri() . ' not found.');
}
/**
* @param $request
* @return Request
*/
public static function create($request)
{
$sRequest = new Request();
$sRequest->fd = $request->fd;
$sRequest->startTime = microtime(true);
$sRequest->params = new HttpParams(Help::toArray($request->rawContent()), $request->get, $request->files);
if (!empty($request->post)) {
$sRequest->params->setPosts($request->post ?? []);
}
$headers = $request->server;
if (!empty($request->header)) {
$headers = array_merge($headers, $request->header);
}
$sRequest->headers = new HttpHeaders($headers);
$sRequest->parseUri();
return $sRequest;
}
}
-226
View File
@@ -1,226 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/24 0024
* Time: 19:39
*/
namespace HttpServer\Http;
use HttpServer\Application;
use HttpServer\Http\Formatter\HtmlFormatter;
use HttpServer\Http\Formatter\JsonFormatter;
use HttpServer\Http\Formatter\XmlFormatter;
use Exception;
use Snowflake\Core\Help;
use Snowflake\Exception\ComponentException;
use Snowflake\Snowflake;
use Swoole\Http\Response as SResponse;
/**
* Class Response
* @package Snowflake\Snowflake\Http
*/
class Response extends Application
{
const JSON = 'json';
const XML = 'xml';
const HTML = 'html';
/** @var string */
public $format = null;
/** @var int */
public $statusCode = 200;
/** @var SResponse */
public $response;
public $isWebSocket = false;
public $headers = [];
private $startTime = 0;
private $_format_maps = [
self::JSON => JsonFormatter::class,
self::XML => XmlFormatter::class,
self::HTML => HtmlFormatter::class
];
public $fd = 0;
/**
* @param $format
* @return $this
*/
public function setFormat($format)
{
$this->format = $format;
return $this;
}
/**
* 清理无用数据
*/
public function clear()
{
$this->fd = 0;
$this->isWebSocket = false;
$this->format = null;
}
/**
* @return string
*/
public function getContentType()
{
if ($this->format == null || $this->format == static::JSON) {
return 'application/json;charset=utf-8';
} else if ($this->format == static::XML) {
return 'application/xml;charset=utf-8';
} else {
return 'text/html;charset=utf-8';
}
}
/**
* @return mixed
* @throws Exception
*/
public function sender()
{
return $this->send(func_get_args());
}
/**
* @param $key
* @param $value
*/
public function addHeader($key, $value)
{
$response = Context::getContext('response');
$response->header($key, $value);
}
/**
* @param string $context
* @param int $statusCode
* @param null $response
* @return bool
* @throws Exception
*/
public function send($context = '', $statusCode = 200, $response = null)
{
$sendData = $this->parseData($context);
if ($response instanceof SResponse) {
$this->response = $response;
}
if ($this->response instanceof SResponse) {
return $this->sendData($this->response, $sendData, $statusCode);
} else {
return $this->printResult($sendData);
}
}
/**
* @param $context
* @return mixed
* @throws Exception
*/
private function parseData($context)
{
if (isset($this->_format_maps[$this->format])) {
$config['class'] = $this->_format_maps[$this->format];
} else {
$config['class'] = HtmlFormatter::class;
}
$formatter = Snowflake::createObject($config);
return $formatter->send($context)->getData();
}
/**
* @param $result
* @return string
* @throws Exception
*/
private function printResult($result)
{
$result = Help::toString($result);
$string = 'Command Result: ' . PHP_EOL;
$string .= empty($result) ? 'success!' : $result . PHP_EOL;
$string .= 'Command Success!' . PHP_EOL;
echo $string;
$event = Snowflake::app()->event;
$event->trigger('CONSOLE_END');
return 'ok';
}
/**
* @param $response
* @param $sendData
* @param $status
* @return mixed
*/
private function sendData($response, $sendData, $status)
{
$response->status($status);
$response->header('Content-Type', $this->getContentType());
$response->header('Access-Control-Allow-Origin', '*');
$response->header('Run-Time', $this->getRuntime());
return $response->end($sendData);
}
/**
* @param $url
* @param array $param
* @return int
*/
public function redirect($url, array $param = [])
{
if (!empty($param)) {
$url .= '?' . http_build_query($param);
}
$url = ltrim($url, '/');
if (!preg_match('/^http/', $url)) {
$url = '/' . $url;
}
return $this->response->redirect($url);
}
/**
* @param null $response
* @return mixed
* @throws ComponentException
*/
public static function create($response = null)
{
$ciResponse = Snowflake::app()->clone('response');
$ciResponse->response = $response;
$ciResponse->startTime = microtime(true);
$ciResponse->format = self::JSON;
return $ciResponse;
}
/**
* @throws Exception
*/
public function sendNotFind()
{
$this->format = static::HTML;
$this->send('', 404);
}
/**
* @return string
*/
public function getRuntime()
{
return sprintf('%.5f', microtime(TRUE) - $this->startTime);
}
}
-18
View File
@@ -1,18 +0,0 @@
<?php
namespace HttpServer\IInterface;
/**
* Interface AuthIdentity
* @package Snowflake\Snowflake\Http
*/
interface AuthIdentity
{
public function getIdentity();
}
-28
View File
@@ -1,28 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/8 0008
* Time: 17:29
*/
namespace HttpServer\IInterface;
/**
* Interface IFormatter
* @package Snowflake\Snowflake\Http\Formatter
*/
interface IFormatter
{
/**
* @param $context
* @return static
*/
public function send($context);
public function getData();
public function clear();
}
-16
View File
@@ -1,16 +0,0 @@
<?php
namespace HttpServer\IInterface;
use HttpServer\Http\Request;
use Closure;
interface Interceptor
{
public function Interceptor(Request $request, Closure $closure);
}
-15
View File
@@ -1,15 +0,0 @@
<?php
namespace HttpServer\IInterface;
use HttpServer\Http\Request;
use Closure;
interface Limits
{
public function next(Request $request, Closure $closure);
}
-18
View File
@@ -1,18 +0,0 @@
<?php
namespace HttpServer\IInterface;
use HttpServer\Http\Request;
/**
* Interface IMiddleware
* @package Snowflake\Snowflake\Route
*/
interface Middleware
{
public function handler(Request $request,\Closure $next);
}
@@ -1,10 +0,0 @@
<?php
namespace HttpServer\IInterface;
interface RouterInterface
{
}
-13
View File
@@ -1,13 +0,0 @@
<?php
namespace HttpServer\IInterface;
interface Service
{
public function onInit();
}
-14
View File
@@ -1,14 +0,0 @@
<?php
namespace HttpServer\IInterface;
interface Task
{
public function getParams();
public function handler();
}
@@ -1,96 +0,0 @@
<?php
namespace HttpServer\Route\Annotation;
use ReflectionClass;
use ReflectionException;
use Snowflake\Abstracts\BaseAnnotation;
use Snowflake\Snowflake;
/**
* Class Annotation
*/
class Annotation extends \Snowflake\Annotation\Annotation
{
const HTTP_EVENT = 'http:event:';
const CLOSE = 'Close';
/**
* @var string
* @Interceptor(LoginInterceptor)
*/
private $Interceptor = 'required|not empty';
/**
* @var string
*/
private $Limits = 'required|not empty';
protected $_annotations = [];
/**
* @param ReflectionClass $reflect
* @param $method
* @param $annotations
* @return mixed|null
* @throws ReflectionException
*/
public function read($reflect, $method, $annotations)
{
$method = $reflect->getMethod($method);
$_annotations = $this->getDocCommentAnnotation($annotations, $method->getDocComment());
$array = [];
foreach ($_annotations as $keyName => $annotation) {
if (!in_array($keyName, $annotations)) {
continue;
}
$array[$keyName] = $this->pop($this->getName(...$annotation));
}
return $array;
}
/**
* @param $controller
* @param $methodName
* @param $events
* @return array|void
* @throws
*/
public function createHandler($controller, $methodName, $events)
{
return Snowflake::createObject($events[2]);
}
/**
* @param $events
* @return bool
*/
public function isLegitimate($events)
{
return isset($events[2]) && !empty($events[2]);
}
/**
* @param $name
* @param $events
* @return false|string
*/
public function getName($name, $events)
{
return self::HTTP_EVENT . $name . ':' . $events[2];
}
}
-68
View File
@@ -1,68 +0,0 @@
<?php
namespace HttpServer\Route\Annotation;
use Snowflake\Annotation\Annotation;
/**
* Class Tcp
* @package HttpServer\Route\Annotation
*/
class Tcp extends Annotation
{
const CONNECT = 'Connect';
const PACKET = 'Packet';
const RECEIVE = 'Receive';
const CLOSE = 'Close';
private $Message = 'required|not empty';
private $Handshake;
private $Close;
/**
* @param $controller
* @param $methodName
* @param $events
* @return array
*/
public function createHandler($controller, $methodName, $events)
{
return [$controller, $methodName];
}
/**
* @param $events
* @return bool|void
*/
public function isLegitimate($events)
{
return true;
}
/**
* @param $events
* @param $comment
* @return false|string
*/
public function getName($events, $comment = [])
{
$prefix = 'TCP:ANNOTATION:' . ltrim($events, ':');
if (isset($comment[2]) && !empty($comment[2])) {
return $prefix . ':' . $comment[2];
}
return $prefix;
}
}
@@ -1,64 +0,0 @@
<?php
namespace HttpServer\Route\Annotation;
use Snowflake\Annotation\Annotation;
/**
* Class Websocket
* @package Snowflake\Annotation
*/
class Websocket extends Annotation
{
const MESSAGE = 'Message';
const HANDSHAKE = 'Handshake';
const CLOSE = 'Close';
private $Message = 'required|not empty';
private $Handshake;
private $Close;
/**
* @param $controller
* @param $methodName
* @param $events
* @return array
*/
public function createHandler($controller, $methodName, $events)
{
return [$controller, $methodName];
}
/**
* @param $events
* @return bool|void
*/
public function isLegitimate($events)
{
return true;
}
/**
* @param $events
* @param $comment
* @return false|string
*/
public function getName($events, $comment = [])
{
$prefix = 'WEBSOCKET:ANNOTATION:' . ltrim($events, ':');
if (isset($comment[2]) && !empty($comment[2])) {
return $prefix . ':' . $comment[2];
}
return $prefix;
}
}
-39
View File
@@ -1,39 +0,0 @@
<?php
namespace HttpServer\Route;
/**
* Class Any
* @package Snowflake\Snowflake\Route
*/
class Any
{
private $nodes = [];
/**
* Any constructor.
* @param array $nodes
*/
public function __construct(array $nodes)
{
$this->nodes = $nodes;
}
/**
* @param $name
* @param $arguments
* @return $this
*/
public function __call($name, $arguments)
{
foreach ($this->nodes as $node) {
$node->{$name}(...$arguments);
}
return $this;
}
}
-41
View File
@@ -1,41 +0,0 @@
<?php
namespace HttpServer\Route;
use Closure;
use Exception;
use HttpServer\Http\Context;
use HttpServer\Http\Request;
use HttpServer\Http\Response;
/**
* Class CoreMiddleware
* @package Snowflake\Snowflake\Route
* 跨域中间件
*/
class CoreMiddleware implements \HttpServer\IInterface\Middleware
{
/**
* @param Request $request
* @param Closure $next
* @return mixed
* @throws Exception
*/
public function handler(Request $request, Closure $next)
{
$header = $request->headers;
/** @var Response $response */
$response = Context::getContext('response');
$request_method = $header->getHeader('access-control-request-method');
$request_headers = $header->getHeader('access-control-request-headers');
$response->addHeader('Access-Control-Allow-Headers', $request_headers);
$response->addHeader('Access-Control-Request-Method', $request_method);
return $next($request);
}
}
-85
View File
@@ -1,85 +0,0 @@
<?php
namespace HttpServer\Route\Dispatch;
use HttpServer\Controller;
use HttpServer\Http\Context;
use Snowflake\Snowflake;
/**
* Class Dispatch
* @package HttpServer\Route\Dispatch
*/
class Dispatch
{
protected $handler;
protected $request;
/**
* @param $handler
* @param $request
* @return static
*/
public static function create($handler, $request)
{
$class = new static();
$class->handler = $handler;
$class->request = $request;
if ($handler instanceof \Closure) {
$class->bind();
}
$class->bindParam();
return $class;
}
/**
* @return mixed
* 执行函数
*/
public function dispatch()
{
return call_user_func($this->handler, $this->request);
}
/**
* 设置作用域
*/
protected function bind()
{
$class = $this->bindRequest(new Controller());
$this->handler = \Closure::bind($this->handler, $class);
}
/**
* @param $controller
* @return mixed
*/
protected function bindRequest($controller)
{
$controller->request = Context::getContext('request');
$controller->headers = $controller->request->headers;
$controller->input = $controller->request->params;
return $controller;
}
/**
* 参数绑定
*/
protected function bindParam()
{
if ($this->handler instanceof \Closure) {
return;
}
$controller = $this->handler[0];
$this->bindRequest($controller);
}
}
-130
View File
@@ -1,130 +0,0 @@
<?php
namespace HttpServer\Route;
use HttpServer\Exception\AuthException;
use HttpServer\Route\Filter\BodyFilter;
use HttpServer\Route\Filter\FilterException;
use HttpServer\Route\Filter\HeaderFilter;
use HttpServer\Route\Filter\QueryFilter;
use Exception;
use HttpServer\Application;
use Snowflake\Snowflake;
/**
* Class Filter
* @package Snowflake\Snowflake\Route
*/
class Filter extends Application
{
/** @var Filter\Filter[] */
private $_filters = [];
/** @var array */
public $grant = [];
/**
* @param array $value
* @return BodyFilter|bool
* @throws Exception
*/
public function setBody(array $value)
{
if (empty($value)) {
return true;
}
/** @var BodyFilter $class */
$class = Snowflake::createObject(BodyFilter::class);
$class->rules = [];
$class->params = Input()->params();
return $this->_filters[] = $class;
}
/**
* @param array $value
* @return HeaderFilter|bool
* @throws Exception
*/
public function setHeader(array $value)
{
if (empty($value)) {
return true;
}
/** @var HeaderFilter $class */
$class = Snowflake::createObject(HeaderFilter::class);
$class->rules = [];
$class->params = request()->headers->getHeaders();
return $this->_filters[] = $class;
}
/**
* @param array $value
* @return QueryFilter|bool
* @throws Exception
*/
public function setQuery(array $value)
{
if (empty($value)) {
return true;
}
/** @var QueryFilter $class */
$class = Snowflake::createObject(QueryFilter::class);
$class->rules = [];
$class->params = request()->headers->getHeaders();
return $this->_filters[] = $class;
}
/**
* @throws Exception
*/
public function handler()
{
if (($error = $this->filters()) !== true) {
throw new FilterException($error);
}
if (!$this->grant()) {
throw new AuthException('Authentication error.');
}
return true;
}
/**
* @return bool
*/
private function filters()
{
if (empty($this->_filters)) {
return true;
}
foreach ($this->_filters as $filter) {
if (!$filter->check()) {
return false;
}
}
return true;
}
/**
* @return bool|mixed
*/
private function grant()
{
if (!is_callable($this->grant, true)) {
return true;
}
return call_user_func($this->grant);
}
}
-25
View File
@@ -1,25 +0,0 @@
<?php
namespace HttpServer\Route\Filter;
use Exception;
/**
* Class BodyFilter
* @package Snowflake\Snowflake\Route\Filter
*/
class BodyFilter extends Filter
{
/**
* @return bool
* @throws Exception
*/
public function check()
{
return $this->validator();
}
}
-46
View File
@@ -1,46 +0,0 @@
<?php
namespace HttpServer\Route\Filter;
use Exception;
use HttpServer\Application;
use validator\Validator;
/**
* Class Filter
* @package Snowflake\Snowflake\Route\Filter
*/
abstract class Filter extends Application
{
public $rules = [];
public $params = [];
abstract public function check();
/**
* @return bool
* @throws Exception
*/
protected function validator()
{
$validator = Validator::getInstance();
$validator->setParams($this->params);
foreach ($this->rules as $val) {
$field = array_shift($val);
if (empty($val)) {
continue;
}
$validator->make($field, $val);
}
if (!$validator->validation()) {
return $this->addError($validator->getError());
}
return true;
}
}
@@ -1,17 +0,0 @@
<?php
namespace HttpServer\Route\Filter;
use Throwable;
class FilterException extends \Exception
{
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
-25
View File
@@ -1,25 +0,0 @@
<?php
namespace HttpServer\Route\Filter;
use Exception;
/**
* Class HeaderFilter
* @package Snowflake\Snowflake\Route\Filter
*/
class HeaderFilter extends Filter
{
/**
* @return bool
* @throws Exception
*/
public function check()
{
return $this->validator();
}
}
-25
View File
@@ -1,25 +0,0 @@
<?php
namespace HttpServer\Route\Filter;
use Exception;
/**
* Class QueryFilter
* @package Snowflake\Snowflake\Route\Filter
*/
class QueryFilter extends Filter
{
/**
* @return bool
* @throws Exception
*/
public function check()
{
return $this->validator();
}
}
-52
View File
@@ -1,52 +0,0 @@
<?php
namespace HttpServer\Route;
use Exception;
use HttpServer\Application;
use Snowflake\Snowflake;
/**
* Class TcpListen
* @package Snowflake\Snowflake\Route
*/
class Handler extends Application
{
/** @var Router */
protected $router;
/**
* Listen constructor.
* @throws Exception
*/
public function __construct()
{
$this->router = Snowflake::app()->router;
parent::__construct([]);
}
/**
* @param $config
* @param $handler
*/
public function group($config, $handler)
{
$this->router->group($config, $handler, $this);
}
/**
* @param $route
* @param $handler
* @return Handler
*/
public function handler($route, $handler)
{
return $this->router->addRoute($route, $handler, 'receive');
}
}
-95
View File
@@ -1,95 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 02:17
*/
namespace HttpServer\Route;
use Closure;
use Exception;
use HttpServer\Route\Dispatch\Dispatch;
/**
* Class Middleware
* @package Snowflake\Snowflake\Route
*/
class Middleware
{
/** @var array */
private $middleWares = [];
/**
* @param $call
* @return $this
*/
public function set($call)
{
$this->middleWares[] = $call;
return $this;
}
/**
* @param array $array
* @return $this
*/
public function setMiddleWares(array $array)
{
$this->middleWares = $array;
return $this;
}
/**
* @param Node $node
* @return mixed
* @throws Exception
*/
public function getGenerate($node)
{
$last = function ($passable) use ($node) {
return Dispatch::create($node->handler, $passable)->dispatch();
};
$middleWares = $this->annotation($node);
$data = array_reduce(array_reverse($middleWares), $this->core(), $last);
$this->middleWares = [];
return $node->callback = $data;
}
/**
* @param Node $node
* @return array
*/
public function annotation($node)
{
$middleWares = $this->middleWares;
if (!$node->hasInterceptor()) {
return $middleWares;
}
foreach ($node->getInterceptor() as $item) {
$middleWares[] = $item[0];
}
return $middleWares;
}
/**
* @return Closure
*/
public function core()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
if ($pipe instanceof \HttpServer\IInterface\Middleware) {
return $pipe->handler($passable, $stack);
} else {
return $pipe($passable, $stack);
}
};
};
}
}
-330
View File
@@ -1,330 +0,0 @@
<?php
namespace HttpServer\Route;
use HttpServer\Http\Request;
use Exception;
use HttpServer\Application;
use HttpServer\Route\Annotation\Annotation;
use Snowflake\Snowflake;
/**
* Class Node
* @package Snowflake\Snowflake\Route
*/
class Node extends Application
{
public $path;
public $index = 0;
public $method;
/** @var Node[] $childes */
public $childes = [];
public $group = [];
public $options = null;
private $_error = '';
public $rules = [];
public $handler;
public $htmlSuffix = '.html';
public $enableHtmlSuffix = false;
public $namespace = [];
public $middleware = [];
public $callback = [];
private $_interceptors = [];
/**
* @param $handler
* @return Node
* @throws
*/
public function bindHandler($handler)
{
if ($handler instanceof \Closure) {
$this->handler = $handler;
} else if (is_string($handler) && strpos($handler, '@') !== false) {
list($controller, $action) = explode('@', $handler);
if (!empty($this->namespace)) {
$controller = implode('\\', $this->namespace) . '\\' . $controller;
}
$this->handler = $this->getReflect($controller, $action);
} else if ($handler != null && !is_callable($handler, true)) {
$this->_error = 'Controller is con\'t exec.';
} else {
$this->handler = $handler;
}
return $this->restructure();
}
/**
* @return bool
*/
public function hasInterceptor()
{
return count($this->_interceptors) > 0;
}
/**
* @return array
*/
public function getInterceptor()
{
return $this->_interceptors;
}
/**
* @param $request
* @return bool
*/
public function methodAllow(Request $request)
{
if ($this->method == $request->getMethod()) {
return true;
}
return $this->method == 'any';
}
/**
* @return bool
* @throws Exception
*/
public function checkSuffix()
{
if ($this->enableHtmlSuffix) {
$url = request()->getUri();
$nowLength = strlen($this->htmlSuffix);
if (strpos($url, $this->htmlSuffix) !== strlen($url) - $nowLength) {
return false;
}
}
return $this->checkRule();
}
/**
* @return bool
* @throws Exception
*/
private function checkRule()
{
if (empty($this->rules)) {
return true;
}
foreach ($this->rules as $rule) {
if (!isset($rule['class'])) {
$rule['class'] = Filter::class;
}
/** @var Filter $object */
$object = Snowflake::createObject($rule);
if (!$object->handler()) {
return false;
};
}
return true;
}
/**
* @param string $controller
* @param string $action
* @return null|array
* @throws Exception
*/
private function getReflect(string $controller, string $action)
{
try {
$reflect = Snowflake::getDi()->getReflect($controller);
if (!$reflect->isInstantiable()) {
throw new Exception($controller . ' Class is con\'t Instantiable.');
}
if (!empty($action) && !$reflect->hasMethod($action)) {
throw new Exception('method ' . $action . ' not exists at ' . $controller . '.');
}
/** @var Annotation $annotation */
$annotation = Snowflake::app()->annotation->get('http');
if (!empty($annotations = $annotation->getAnnotation(Annotation::class))) {
$this->_interceptors = $annotation->read($reflect, $action, $annotations);
}
return [$reflect->newInstance(), $action];
} catch (Exception $exception) {
$this->_error = $exception->getMessage();
$this->error($exception->getMessage(), 'router');
return null;
}
}
/**
* @return string
* 错误信息
*/
public function getError()
{
return $this->_error;
}
/**
* @param Node $node
* @param string $field
* @return Node
*/
public function addChild(Node $node, string $field)
{
/** @var Node $oLod */
$oLod = $this->childes[$field] ?? null;
if (!empty($oLod)) {
$node = $oLod;
}
$this->childes[$field] = $node;
return $this->childes[$field];
}
/**
* @param $rule
* @return $this
*/
public function filter($rule)
{
if (empty($rule)) {
return $this;
}
if (!isset($rule[0])) {
$rule = [$rule];
}
foreach ($rule as $value) {
if (empty($value)) {
continue;
}
$this->rules[] = $value;
}
return $this;
}
/**
* @param string $search
* @return Node|mixed
*/
public function findNode(string $search)
{
if (empty($this->childes)) {
return null;
}
if (isset($this->childes[$search])) {
return $this->childes[$search];
}
$_searchMatch = '/<(\w+)?:(.+)?>/';
foreach ($this->childes as $key => $val) {
if (preg_match($_searchMatch, $key, $match)) {
\Input()->addGetParam($match[1] ?? '--', $search);
return $this->childes[$key];
}
}
return null;
}
/**
* @param $options
* @return $this
*/
public function bindOptions($options)
{
if (is_object($options)) {
$this->options = $options;
} else {
$options = array_filter($options);
$last = $options[count($options) - 1];
if (empty($last)) {
return $this;
}
$this->options = $last;
}
return $this;
}
/**
* @param string $alias
* @return $this
* 别称
*/
public function alias(string $alias)
{
$_alias = $alias;
return $this;
}
/**
* @param int $limit
* @param int $duration
* @param bool $isBindConsumer
* @return $this
* @throws Exception
*/
public function limits(int $limit, int $duration = 60, bool $isBindConsumer = false)
{
$limits = Snowflake::app()->getLimits();
$limits->addLimits($this->path, $limit, $duration, $isBindConsumer);
return $this;
}
/**
* @param $middles
* @throws
*/
public function bindMiddleware(array $middles)
{
$_tmp = [];
if (empty($middles)) {
return;
}
$this->middleware = $this->each($middles, $_tmp);
$this->restructure();
}
/**
* @throws Exception
*/
private function restructure()
{
if (empty($this->handler)) {
return $this;
}
$made = Snowflake::createObject(Middleware::class);
$made->setMiddleWares($this->middleware);
$made->getGenerate($this);
return $this;
}
/**
* @param $array
* @param $_temp
* @return array
* @throws Exception
*/
private function each($array, $_temp)
{
if (empty($array)) {
return $_temp;
}
foreach ($array as $class) {
if (is_array($class)) {
$_temp = $this->each($class, $_temp);
} else {
$_temp[] = Snowflake::createObject($class);
}
}
return $_temp;
}
}
-514
View File
@@ -1,514 +0,0 @@
<?php
namespace HttpServer\Route;
use Closure;
use Exception;
use HttpServer\Http\Context;
use HttpServer\Controller;
use HttpServer\IInterface\RouterInterface;
use HttpServer\Application;
use HttpServer\Route\Annotation\Annotation;
use ReflectionException;
use Snowflake\Config;
use Snowflake\Core\JSON;
use Snowflake\Exception\ConfigException;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
/**
* Class Router
* @package Snowflake\Snowflake\Route
*/
class Router extends Application implements RouterInterface
{
/** @var Node[] $nodes */
public $nodes = [];
public $groupTacks = [];
public $dir = 'App\\Http\\Controllers';
/** @var string[] */
public $methods = ['get', 'post', 'options', 'put', 'delete', 'receive'];
/**
* @throws ConfigException
* 初始化函数路径
*/
public function init()
{
$this->dir = Config::get('http.namespace', false, $this->dir);
}
/**
* @param $path
* @param $handler
* @param string $method
* @return mixed|Node|null
* @throws
*/
public function addRoute($path, $handler, $method = 'any')
{
if (!isset($this->nodes[$method])) {
$this->nodes[$method] = [];
}
list($first, $explode) = $this->split($path);
$parent = $this->nodes[$method][$first] ?? null;
if (empty($parent)) {
$parent = $this->NodeInstance($first, 0, $method);
$this->nodes[$method][$first] = $parent;
}
if ($first !== '/') {
$parent = $this->bindNode($parent, $explode, $method);
}
return $parent->bindHandler($handler);
}
/**
* @param Node $parent
* @param array $explode
* @param $method
* @return Node
*/
private function bindNode($parent, $explode, $method)
{
$a = 0;
if (empty($explode)) {
return $parent->addChild($this->NodeInstance('/', $a, $method), '/');
}
foreach ($explode as $value) {
if (empty($value)) {
continue;
}
++$a;
$search = $parent->findNode($value);
if ($search === null) {
$parent = $parent->addChild($this->NodeInstance($value, $a, $method), $value);
} else {
$parent = $search;
}
}
return $parent;
}
/**
* @param $route
* @param $handler
* @return Node|mixed|null
*/
public function socket($route, $handler)
{
return $this->addRoute($route, $handler, 'socket');
}
/**
* @param $route
* @param $handler
* @param int $port
* @return Node|mixed|null
*/
public function gRpc($route, $handler, $port = 33007)
{
$route = ltrim($route, '/');
if (!empty($port)) {
$route = $port . '/' . $route;
}
return $this->addRoute($route, $handler, 'grpc');
}
/**
* @param $route
* @param $handler
* @return Node|mixed|null
*/
public function task($route, $handler)
{
return $this->addRoute($route, $handler, 'Task');
}
/**
* @param $route
* @param $handler
* @return mixed|Node|null
* @throws
*/
public function post($route, $handler)
{
return $this->addRoute($route, $handler, 'post');
}
/**
* @param $route
* @param $handler
* @return mixed|Node|null
* @throws
*/
public function get($route, $handler)
{
return $this->addRoute($route, $handler, 'get');
}
/**
* @param $route
* @param $handler
* @return mixed|Node|null
* @throws
*/
public function options($route, $handler)
{
return $this->addRoute($route, $handler, 'options');
}
/**
* @param $port
* @param Closure $closure
* @throws
*/
public function listen(int $port, Closure $closure)
{
$stdClass = Snowflake::createObject(Handler::class);
$this->group(['prefix' => $port], $closure, $stdClass);
}
/**
* @param $route
* @param $handler
* @return Any
*/
public function any($route, $handler)
{
$nodes = [];
foreach (['get', 'post', 'options', 'put', 'delete'] as $method) {
$nodes[] = $this->addRoute($route, $handler, $method);
}
return new Any($nodes);
}
/**
* @param $route
* @param $handler
* @return mixed|Node|null
* @throws
*/
public function delete($route, $handler)
{
return $this->addRoute($route, $handler, 'delete');
}
/**
* @param $route
* @param $handler
* @return mixed|Node|null
* @throws
*/
public function put($route, $handler)
{
return $this->addRoute($route, $handler, 'put');
}
/**
* @param $value
* @param $index
* @param $method
* @return Node
* @throws
*/
public function NodeInstance($value, $index = 0, $method = 'get')
{
$node = new Node();
$node->childes = [];
$node->path = $value;
$node->index = $index;
$node->method = $method;
$name = array_column($this->groupTacks, 'namespace');
$dir = array_column($this->groupTacks, 'dir');
if (!empty($dir)) {
array_unshift($name, implode('\\', $dir));
} else {
if ($method == 'package' || $method == 'receive') {
$dir = 'App\\Listener';
} else {
$dir = $this->dir;
}
array_unshift($name, $dir);
}
if (!empty($name) && $name = array_filter($name)) {
$node->namespace = $name;
}
$name = array_column($this->groupTacks, 'middleware');
if (!empty($name) && $name = array_filter($name)) {
$node->bindMiddleware($name);
}
$options = array_column($this->groupTacks, 'options');
if (!empty($options) && is_array($options)) {
$node->bindOptions($options);
}
$rules = array_column($this->groupTacks, 'filter');
$rules = array_shift($rules);
if (!empty($rules) && is_array($rules)) {
$node->filter($rules);
}
return $node;
}
/**
* @param array $config
* @param callable $callback
* 路由分组
* @param null $stdClass
*/
public function group(array $config, callable $callback, $stdClass = null)
{
$this->groupTacks[] = $config;
if ($stdClass) {
$callback($stdClass);
} else {
$callback($this);
}
array_pop($this->groupTacks);
}
/**
* @return string
*/
public function addPrefix()
{
$prefix = array_column($this->groupTacks, 'prefix');
$prefix = array_filter($prefix);
if (empty($prefix)) {
return '';
}
return '/' . implode('/', $prefix);
}
/**
* @param array $explode
* @param $method
* @return Node|null
* 查找指定路由
*/
public function tree_search($explode, $method)
{
if (empty($explode)) {
return $this->nodes[$method]['/'] ?? null;
}
$first = array_shift($explode);
if (!($parent = $this->nodes[$method][$first] ?? null)) {
return null;
}
if (empty($explode)) {
return $parent->findNode('/');
}
while ($value = array_shift($explode)) {
$node = $parent->findNode($value);
if (!$node) {
break;
}
$parent = $node;
}
return $parent;
}
/**
* @param $path
* @return array
* '*'
*/
public function split($path)
{
$prefix = $this->addPrefix();
$path = ltrim($path, '/');
if (!empty($prefix)) {
$path = $prefix . '/' . $path;
}
$explode = array_filter(explode('/', $path));
if (empty($explode)) {
return ['/', []];
}
$first = array_shift($explode);
if (empty($explode)) {
$explode = [];
}
return [$first, $explode];
}
/**
* @return array
*/
public function each()
{
$paths = [];
foreach ($this->nodes as $node) {
/** @var Node[] $node */
foreach ($node as $_node) {
if ($_node->path == '/') {
continue;
}
$path = strtoupper($_node->method) . ' : ' . $_node->path;
if (!empty($_node->childes)) {
$path = $this->readByChild($_node->childes, $path);
}
$paths[] = $path;
}
}
return $this->readByArray($paths);
}
/**
* @param $array
* @param array $returns
* @return array
*/
private function readByArray($array, $returns = [])
{
foreach ($array as $value) {
if (empty($value)) {
continue;
}
if (is_array($value)) {
$returns = $this->readByArray($value, $returns);
} else {
[$method, $route] = explode(' : ', $value);
$returns[] = ['method' => $method, 'route' => $route];
}
}
return $returns;
}
/**
* @param $child
* @param string $paths
* @return array
*/
private function readByChild($child, $paths = '')
{
$newPath = [];
/** @var Node $item */
foreach ($child as $item) {
if ($item->path == '/') {
continue;
}
if (!empty($item->childes)) {
$newPath[] = $this->readByChild($item->childes, $paths . '/' . $item->path);
} else {
[$first, $route] = explode(' : ', $paths);
$newPath[] = strtoupper($item->method) . ' : ' . $route . '/' . $item->path;
}
}
return $newPath;
}
/**
* @return mixed
* @throws
*/
public function dispatch()
{
$request = Context::getContext('request');
if (!($node = $this->find_path($request))) {
return JSON::to(404, 'Page not found.');
}
if (empty($node->callback)) {
if (!empty($node->getError())) {
return JSON::to(500, $node->getError());
}
return JSON::to(404, 'Page not found.');
}
return call_user_func($node->callback, $request);
}
/**
* @param $request
* @return Node|false|int|mixed|string|null
*/
private function find_path($request)
{
$node = $this->tree_search($request->getExplode(), $request->getMethod());
if ($node instanceof Node) {
return $node;
}
if (!$request->isOption) {
return null;
}
$node = $this->tree_search(['*'], $request->getMethod());
if (!($node instanceof Node)) {
return null;
}
return $node;
}
/**
* @throws
*/
public function loadRouterSetting()
{
$prefix = APP_PATH . 'app/Http/';
/** @var Annotation $annotation */
$annotation = Snowflake::app()->annotation;
$annotation->register('http', Annotation::class);
$annotation = $annotation->get('http');
$annotation->registration_notes($prefix . 'Interceptor', 'App\Http\Interceptor');
$annotation->registration_notes($prefix . 'Limits', 'App\Http\Limits');
$this->loadRouteDir(APP_PATH . '/routes');
}
/**
* @param $path
* @throws Exception
* 加载目录下的路由文件
*/
private function loadRouteDir($path)
{
$files = glob($path . '/*');
for ($i = 0; $i < count($files); $i++) {
if (is_dir($files[$i])) {
$this->loadRouteDir($files[$i]);
} else {
$this->loadRouterFile($files[$i]);
}
}
}
/**
* @param $files
* @throws Exception
*/
private function loadRouterFile($files)
{
try {
$router = $this;
include_once "{$files}";
} catch (Exception $exception) {
$this->error($exception->getMessage());
} finally {
if (isset($exception)) {
unset($exception);
}
}
}
}
-350
View File
@@ -1,350 +0,0 @@
<?php
namespace HttpServer;
use HttpServer\Events\OnClose;
use HttpServer\Events\OnConnect;
use HttpServer\Events\OnPacket;
use HttpServer\Events\OnReceive;
use HttpServer\Events\OnRequest;
use HttpServer\Route\Annotation\Annotation;
use HttpServer\Route\Annotation\Tcp;
use HttpServer\Service\Http;
use HttpServer\Service\Receive;
use HttpServer\Service\Packet;
use HttpServer\Service\WebSocket;
use Exception;
use ReflectionException;
use Snowflake\Config;
use Snowflake\Core\ArrayAccess;
use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Exception\ConfigException;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
use Swoole\Process;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use Swoole\Runtime;
/**
* Class Server
* @package HttpServer
*
*
* @example [
* ['host'=> '127.0.0.1', 'port'=> 5775, 'mode'=> SWOOLE_TCP],
* ['host'=> '127.0.0.1', 'port'=> 5775, 'mode'=> SWOOLE_TCP],
* ['host'=> '127.0.0.1', 'port'=> 5775, 'mode'=> SWOOLE_TCP],
* ['host'=> '127.0.0.1', 'port'=> 5775, 'mode'=> SWOOLE_TCP],
* ['host'=> '127.0.0.1', 'port'=> 5775, 'mode'=> SWOOLE_UDP],
* ['host'=> '127.0.0.1', 'port'=> 5775, 'mode'=> SWOOLE_TCP]
* ]
*/
class Server extends Application
{
const HTTP = 'HTTP';
const TCP = 'TCP';
const PACKAGE = 'PACKAGE';
const WEBSOCKET = 'WEBSOCKET';
private $listening = [];
private $server = [
'HTTP' => [SWOOLE_TCP, Http::class],
'TCP' => [SWOOLE_TCP, Receive::class],
'PACKAGE' => [SWOOLE_UDP, Packet::class],
'WEBSOCKET' => [SWOOLE_SOCK_TCP, WebSocket::class],
];
/** @var Http|WebSocket|Packet|Receive */
private $baseServer;
/**
* @param array $configs
* @return Http|Packet|Receive|WebSocket
* @throws Exception
*/
public function initCore(array $configs)
{
$annotation = Snowflake::app()->annotation;
$annotation->register('tcp', Tcp::class);
$annotation->register('http', Annotation::class);
$annotation->register('websocket', AWebsocket::class);
$this->enableCoroutine((bool)Config::get('enable_coroutine'));
foreach ($this->sortServers($configs) as $server) {
$this->create($server);
}
$this->onProcessListener();
return $this->getServer();
}
/**
* @return void
*
* start server
* @throws ConfigException
* @throws Exception
*/
public function start()
{
$configs = Config::get('servers', true);
$baseServer = $this->initCore($configs);
$baseServer->start();
}
/**
* @param bool $isEnable
*/
private function enableCoroutine($isEnable = true)
{
if ($isEnable !== true) {
return;
}
Runtime::enableCoroutine(true, SWOOLE_HOOK_TCP |
SWOOLE_HOOK_UNIX |
SWOOLE_HOOK_UDP |
SWOOLE_HOOK_UDG |
SWOOLE_HOOK_SSL |
SWOOLE_HOOK_TLS |
SWOOLE_HOOK_SLEEP |
SWOOLE_HOOK_STREAM_FUNCTION |
SWOOLE_HOOK_PROC
);
}
/**
* @throws ReflectionException
* @throws ConfigException
* @throws NotFindClassException
* @throws Exception
*/
public function onProcessListener()
{
$processes = Config::get('processes');
if (empty($processes) || !is_array($processes)) {
return;
}
$application = Snowflake::app();
foreach ($processes as $name => $process) {
$class = Snowflake::createObject($process);
if (!method_exists($class, 'onHandler')) {
continue;
}
$this->debug(sprintf('Process %s', $process));
$system = new Process([$class, 'onHandler'], false, 1, true);
if (Snowflake::isLinux()) {
$system->name($name);
}
$this->baseServer->addProcess($system);
$application->set(get_class($class), $system);
}
}
/**
* @return Http|WebSocket|Packet|Receive
*/
public function getServer()
{
return $this->baseServer;
}
/**
* @param $config
* @return mixed
* @throws Exception
*/
private function create($config)
{
$settings = Config::get('settings', false, []);
if (!isset($this->server[$config['type']])) {
throw new Exception('Unknown server type(' . $config['type'] . ').');
}
$server = $this->dispatchCreate($config, $settings);
if (isset($config['events'])) {
$this->createEventListen($config);
}
return $server;
}
/**
* @param $config
* @throws Exception
*/
protected function createEventListen($config)
{
if (!is_array($config['events'])) {
return;
}
$event = Snowflake::app()->event;
foreach ($config['events'] as $name => $_event) {
$event->on($name, $_event);
}
}
/**
* @param $config
* @param $settings
* @return mixed
* @throws Exception
*/
private function dispatchCreate($config, $settings)
{
if (!($this->baseServer instanceof \Swoole\Server)) {
$class = $this->dispatch($config['type']);
$this->baseServer = new $class($config['host'], $config['port'], SWOOLE_PROCESS, $config['mode']);
$this->baseServer->set($settings);
$this->bindAnnotation();
} else {
$newListener = $this->baseServer->addlistener($config['host'], $config['port'], $config['mode']);
if (isset($config['settings']) && is_array($config['settings'])) {
$newListener->set($config['settings']);
}
$this->onListenerBind($config, $this->baseServer);
}
return $this->baseServer;
}
/**
* @throws Exception
*/
private function bindAnnotation()
{
if ($this->baseServer instanceof WebSocket) {
$this->onLoadWebsocketHandler();
}
if ($this->baseServer instanceof Http) {
$this->onLoadHttpHandler();
}
}
/**
* @param $config
* @param $newListener
* @throws NotFindClassException
* @throws ReflectionException
* @throws Exception
*/
private function onListenerBind($config, $newListener)
{
$this->debug(sprintf('Listener %s::%d', $config['host'], $config['port']));
if ($config['type'] == self::HTTP) {
$this->onBind($newListener, 'request', [Snowflake::createObject(OnRequest::class), 'onHandler']);
} else if ($config['type'] == self::TCP || $config['type'] == self::PACKAGE) {
$this->onBind($newListener, 'connect', [Snowflake::createObject(OnConnect::class), 'onHandler']);
$this->onBind($newListener, 'close', [Snowflake::createObject(OnClose::class), 'onHandler']);
$this->onBind($newListener, 'packet', [Snowflake::createObject(OnPacket::class), 'onHandler']);
$this->onBind($newListener, 'receive', [Snowflake::createObject(OnReceive::class), 'onHandler']);
} else if ($config['type'] == self::WEBSOCKET) {
throw new Exception('Base server must instanceof \Swoole\WebSocket\Server::class.');
} else {
throw new Exception('Unknown server type(' . $config['type'] . ').');
}
}
/**
* @param $server
* @param $name
* @param $callback
* @throws Exception
*/
private function onBind($server, $name, $callback)
{
if (in_array($name, $this->listening)) {
return;
}
if ($name === 'request') {
$this->onLoadHttpHandler();
}
array_push($this->listening, $name);
$server->on($name, $callback);
}
/**
* Load router handler
* @throws Exception
*/
public function onLoadHttpHandler()
{
$event = Snowflake::app()->getEvent();
$router = Snowflake::app()->getRouter();
if ($event->exists(Event::SERVER_WORKER_START, [$router, 'loadRouterSetting'])) {
return;
}
$event->on(Event::SERVER_WORKER_START, [$router, 'loadRouterSetting']);
}
/**
* @throws Exception
*/
public function onLoadWebsocketHandler()
{
/** @var AWebsocket $websocket */
$websocket = Snowflake::app()->annotation->register('websocket', AWebsocket::class);
$websocket->namespace = 'App\\Websocket';
$websocket->path = APP_PATH . 'app/Websocket';
$event = Snowflake::app()->event;
if ($event->exists(Event::SERVER_WORKER_START, [$websocket, 'registration_notes'])) {
return;
}
$event->on(Event::SERVER_WORKER_START, [$websocket, 'registration_notes']);
}
/**
* @param $type
* @return string
*/
private function dispatch($type)
{
$default = [
self::HTTP => Http::class,
self::WEBSOCKET => WebSocket::class,
self::TCP => Receive::class,
self::PACKAGE => Packet::class
];
return $default[$type] ?? Receive::class;
}
/**
* @param $servers
* @return array
*/
private function sortServers($servers)
{
$array = [];
foreach ($servers as $server) {
switch ($server['type']) {
case self::WEBSOCKET:
array_unshift($array, $server);
break;
case self::HTTP:
case self::PACKAGE | self::TCP:
$array[] = $server;
break;
default:
$array[] = $server;
}
}
return $array;
}
}
-35
View File
@@ -1,35 +0,0 @@
<?php
namespace HttpServer;
use Exception;
use HttpServer\Server;
use Snowflake\Abstracts\Component;
use Snowflake\Abstracts\Providers;
use Snowflake\Config;
use Snowflake\Exception\ConfigException;
use Snowflake\Snowflake;
/**
* Class DatabasesProviders
* @package Database
*/
class ServerProviders extends Providers
{
/**
* @param \Snowflake\Application $application
* @throws Exception
*/
public function onImport(\Snowflake\Application $application)
{
$application->set('server', ['class' => Server::class]);
// /** @var \Console\Application $console */
// $console = $application->get('console');
// $console->register(Command::class);
}
}
-17
View File
@@ -1,17 +0,0 @@
<?php
namespace HttpServer\Service\Abstracts;
use HttpServer\IInterface\Service;
use Swoole\Http\Server;
abstract class Http extends Server implements Service
{
use \HttpServer\Service\Abstracts\Server;
}
-97
View File
@@ -1,97 +0,0 @@
<?php
namespace HttpServer\Service\Abstracts;
use Exception;
use ReflectionException;
use Snowflake\Application;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
trait Server
{
/** @var Application */
public $application;
/**
* Server constructor.
* @param $host
* @param null $port
* @param null $mode
* @param null $sock_type
*/
public function __construct($host, $port = null, $mode = null, $sock_type = null)
{
$this->application = Snowflake::app();
parent::__construct($host, $port, $mode, $sock_type);
}
/**
* @param array $settings
* @return mixed|void
*/
public function set(array $settings)
{
parent::set($settings); // TODO: Change the autogenerated stub
$this->onInit();
}
/**
* @return mixed|void
* @throws NotFindClassException
* @throws ReflectionException
*/
public function onHandlerListener()
{
$this->on('workerStop', $this->createHandler('workerStop'));
$this->on('workerExit', $this->createHandler('workerExit'));
$this->on('workerStart', $this->createHandler('workerStart'));
$this->on('workerError', $this->createHandler('workerError'));
$this->on('managerStart', $this->createHandler('managerStart'));
$this->on('managerStop', $this->createHandler('managerStop'));
$this->on('pipeMessage', $this->createHandler('pipeMessage'));
$this->on('shutdown', $this->createHandler('shutdown'));
$this->on('start', $this->createHandler('start'));
$this->addTask();
}
/**
* @throws NotFindClassException
* @throws ReflectionException
*/
protected function addTask()
{
$settings = $this->setting;
if (($taskNumber = $settings['task_worker_num'] ?? 0) > 0) {
$this->on('finish', $this->createHandler('finish'));
$this->on('task', $this->createHandler('task'));
}
}
/**
* @param $eventName
* @return array
* @throws NotFindClassException
* @throws ReflectionException
* @throws Exception
*/
protected function createHandler($eventName)
{
$classPrefix = 'HttpServer\Events\On' . ucfirst($eventName);
if (!class_exists($classPrefix)) {
throw new Exception('class not found.');
}
$class = Snowflake::createObject($classPrefix, [Snowflake::app()]);
return [$class, 'onHandler'];
}
}
-24
View File
@@ -1,24 +0,0 @@
<?php
namespace HttpServer\Service\Abstracts;
use Closure;
use HttpServer\IInterface\Service;
use Swoole\Server;
abstract class Tcp extends Server implements Service
{
use \HttpServer\Service\Abstracts\Server;
/** @var Closure|array */
public $unpack;
/** @var Closure|array */
public $pack;
}
@@ -1,16 +0,0 @@
<?php
namespace HttpServer\Service\Abstracts;
use HttpServer\IInterface\Service;
use Swoole\WebSocket\Server;
abstract class Websocket extends Server implements Service
{
use \HttpServer\Service\Abstracts\Server;
}
-45
View File
@@ -1,45 +0,0 @@
<?php
namespace HttpServer\Service;
use Exception;
use HttpServer\Http\Context;
use HttpServer\Http\Request as HRequest;
use HttpServer\Http\Response as HResponse;
use ReflectionException;
use Snowflake\Core\JSON;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
use Swoole\Error;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;
use HttpServer\Service\Abstracts\Http as AHttp;
class Http extends AHttp
{
/**
* @throws ReflectionException
* @throws NotFindClassException
*/
public function onInit()
{
$this->onHandlerListener();
$this->onBaseListener();
}
/**
* @throws NotFindClassException
* @throws ReflectionException
*/
public function onBaseListener()
{
$this->on('request', $this->createHandler('request'));
}
}
-46
View File
@@ -1,46 +0,0 @@
<?php
namespace HttpServer\Service;
use Exception;
use HttpServer\Service\Abstracts\Tcp;
use ReflectionException;
use Snowflake\Event;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnPacket
* @package HttpServer\Events
*/
class Packet extends Tcp
{
/**
* @throws ReflectionException
* @throws NotFindClassException
*/
public function onInit()
{
$this->onHandlerListener();
$this->onBaseListener();
}
/**
* @throws NotFindClassException
* @throws ReflectionException
*/
public function onBaseListener()
{
$this->on('connect', $this->createHandler('connect'));
$this->on('packet', $this->createHandler('packet'));
$this->on('close', $this->createHandler('close'));
}
}
-42
View File
@@ -1,42 +0,0 @@
<?php
namespace HttpServer\Service;
use HttpServer\Service\Abstracts\Tcp;
use ReflectionException;
use Snowflake\Exception\NotFindClassException;
/**
* Class Receive
* @package HttpServer\Events
*/
class Receive extends Tcp
{
/**
* @throws ReflectionException
* @throws NotFindClassException
*/
public function onInit()
{
$this->onHandlerListener();
$this->onBaseListener();
}
/**
* @throws NotFindClassException
* @throws ReflectionException
*/
public function onBaseListener()
{
$this->on('connect', $this->createHandler('connect'));
$this->on('receive', $this->createHandler('receive'));
$this->on('close', $this->createHandler('close'));
}
}
-45
View File
@@ -1,45 +0,0 @@
<?php
namespace HttpServer\Service;
use Exception;
use ReflectionException;
use Snowflake\Error\Logger;
use Snowflake\Event;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
use Swoole\Http\Request as SRequest;
use Swoole\Http\Response as SResponse;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
use HttpServer\Service\Abstracts\Websocket as HAWebsocket;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
class Websocket extends HAWebsocket
{
/**
* @throws ReflectionException
* @throws NotFindClassException
*/
public function onInit()
{
$this->onHandlerListener();
$this->onBaseListener();
}
/**
* @throws NotFindClassException
* @throws ReflectionException
*/
public function onBaseListener()
{
$this->on('handshake', $this->createHandler('handshake'));
$this->on('message', $this->createHandler('message'));
$this->on('close', $this->createHandler('close'));
}
}
-111
View File
@@ -1,111 +0,0 @@
<?php
use HttpServer\Route\Router;
use HttpServer\Server;
use Snowflake\Snowflake;
use Snowflake\Event;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\WebSocket\Frame;
return [
'servers' => [
[
'id' => '',
'type' => Server::HTTP,
'host' => '127.0.0.1',
'port' => 9527,
'settings' => [
'worker_num' => 10,
'enable_coroutine' => 1
],
'events' => [
Event::SERVER_WORKER_START => function () {
$router = Snowflake::app()->router;
$router->loadRouterSetting();
},
]
],
[
'id' => '',
'type' => Server::PACKAGE,
'host' => '127.0.0.1',
'port' => 9628,
'settings' => [
'worker_num' => 10,
'enable_coroutine' => 1
],
'message' => [
'pack' => function ($data) {
return \Snowflake\Core\JSON::encode($data);
},
'unpack' => function ($data) {
return \Snowflake\Core\JSON::decode($data);
},
],
'events' => [
]
],
[
'id' => '',
'type' => Server::TCP,
'host' => '127.0.0.1',
'port' => 9629,
'settings' => [
'worker_num' => 10,
'enable_coroutine' => 1
],
'message' => [
'pack' => function ($data) {
return \Snowflake\Core\JSON::encode($data);
},
'unpack' => function ($data) {
return \Snowflake\Core\JSON::decode($data);
},
],
'events' => [
Event::RECEIVE_CONNECTION => function ($data) {
return 'hello word~';
}
]
],
[
'id' => '',
'type' => Server::WEBSOCKET,
'host' => '127.0.0.1',
'port' => 9530,
'settings' => [
'worker_num' => 10,
'enable_coroutine' => 1
],
'events' => [
Event::SERVER_WORKER_START => function () {
$path = APP_PATH . 'app/Websocket';
$websocket = Snowflake::app()->annotation->websocket;
$websocket->registration_notes($path, 'App\\Sockets\\');
},
Event::SERVER_HANDSHAKE => function (Request $request, Response $response) {
$this->error($request->fd . ' connect.');
$response->status(101);
$response->end();
},
Event::SERVER_MESSAGE => function (\Swoole\WebSocket\Server $server, Frame $frame) {
$this->error('websocket SERVER_MESSAGE.');
if (is_null($json = json_decode($frame->data, true))) {
return $server->push($frame->fd, 'format error~');
}
$websocket = Snowflake::app()->annotation->websocket;
if ($websocket->has($json['path'])) {
return $websocket->runWith($json['path'], [$frame->fd, $json]);
} else {
return $server->push($frame->fd, 'hello word~');
}
},
Event::SERVER_CLOSE => function (int $fd) {
$this->error($fd . ' disconnect.');
return 'hello word~';
}
]
],
]
];