add Middleware

This commit is contained in:
whale
2020-03-25 18:35:16 +08:00
parent 50a64d2d0b
commit 6861d27629
11 changed files with 199 additions and 39 deletions

View File

@@ -46,8 +46,6 @@ class ZMBuf
// Atomic可跨进程读写的原子计数任何地方均可使用 // Atomic可跨进程读写的原子计数任何地方均可使用
/** @var null|swoole_atomic */ /** @var null|swoole_atomic */
static $info_level = null;//保存log等级的原子计数 static $info_level = null;//保存log等级的原子计数
/** @var swoole_atomic $reload_time */
public static $events = []; public static $events = [];
/** @var Atomic[] */ /** @var Atomic[] */
public static $atomics; public static $atomics;

View File

@@ -6,7 +6,6 @@ namespace Module\Example;
use Framework\Console; use Framework\Console;
use ZM\Annotation\CQ\CQCommand; use ZM\Annotation\CQ\CQCommand;
use ZM\Annotation\Http\Controller;
use ZM\Annotation\Http\RequestMapping; use ZM\Annotation\Http\RequestMapping;
use ZM\Annotation\Swoole\SwooleEventAt; use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Connection\CQConnection; use ZM\Connection\CQConnection;
@@ -15,7 +14,6 @@ use ZM\ModBase;
/** /**
* Class Hello * Class Hello
* @package Module\Example * @package Module\Example
* @Controller("/view")
*/ */
class Hello extends ModBase class Hello extends ModBase
{ {
@@ -34,17 +32,10 @@ class Hello extends ModBase
} }
/** /**
* @RequestMapping("/test/{ping}") * @RequestMapping("/test/ping")
*/
public function ping($param){
return "You input id is: ".$param["ping"];
}
/**
* @RequestMapping("/test/pong")
*/ */
public function pong(){ public function pong(){
$this->response->end("ping"); return "pong";
} }
/** /**

View File

@@ -10,7 +10,12 @@ use ReflectionClass;
use ReflectionException; use ReflectionException;
use ReflectionMethod; use ReflectionMethod;
use ZM\Annotation\CQ\{CQAfter, CQBefore, CQCommand, CQMessage, CQMetaEvent, CQNotice, CQRequest}; use ZM\Annotation\CQ\{CQAfter, CQBefore, CQCommand, CQMessage, CQMetaEvent, CQNotice, CQRequest};
use ZM\Annotation\Http\After;
use ZM\Annotation\Http\Before;
use ZM\Annotation\Http\Controller; use ZM\Annotation\Http\Controller;
use ZM\Annotation\Http\HandleException;
use ZM\Annotation\Http\Middleware;
use ZM\Annotation\Http\MiddlewareClass;
use ZM\Annotation\Http\RequestMapping; use ZM\Annotation\Http\RequestMapping;
use ZM\Annotation\Interfaces\CustomAnnotation; use ZM\Annotation\Interfaces\CustomAnnotation;
use ZM\Annotation\Interfaces\Level; use ZM\Annotation\Interfaces\Level;
@@ -22,6 +27,7 @@ use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt; use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Annotation\Interfaces\Rule; use ZM\Annotation\Interfaces\Rule;
use ZM\Connection\WSConnection; use ZM\Connection\WSConnection;
use ZM\Http\MiddlewareInterface;
use ZM\Utils\DataProvider; use ZM\Utils\DataProvider;
class AnnotationParser class AnnotationParser
@@ -31,8 +37,7 @@ class AnnotationParser
* @throws ReflectionException * @throws ReflectionException
* @throws AnnotationException * @throws AnnotationException
*/ */
public static function registerMods() public static function registerMods() {
{
self::loadAnnotationClasses(); self::loadAnnotationClasses();
$all_class = getAllClasses(WORKING_DIR . "/src/Module/", "Module"); $all_class = getAllClasses(WORKING_DIR . "/src/Module/", "Module");
ZMBuf::$req_mapping[0] = [ ZMBuf::$req_mapping[0] = [
@@ -55,6 +60,26 @@ class AnnotationParser
DataProvider::addSaveBuffer($vs->buf_name, $vs->sub_folder); DataProvider::addSaveBuffer($vs->buf_name, $vs->sub_folder);
} elseif ($vs instanceof InitBuffer) { } elseif ($vs instanceof InitBuffer) {
ZMBuf::set($vs->buf_name, []); ZMBuf::set($vs->buf_name, []);
} elseif ($vs instanceof MiddlewareClass) {
$result = [
"class" => "\\".$reflection_class->getName()
];
foreach ($methods as $vss) {
$method_annotations = $reader->getMethodAnnotations($vss);
foreach ($method_annotations as $vsss) {
if ($vss instanceof Rule) $vss = self::registerRuleEvent($vsss, $vss, $reflection_class);
else $vss = self::registerMethod($vsss, $vss, $reflection_class);
echo get_class($vsss).PHP_EOL;
if ($vsss instanceof Before) $result["before"] = $vsss->method;
if ($vsss instanceof After) $result["after"] = $vsss->method;
if ($vsss instanceof HandleException) {
$result["exception"] = $vsss->class_name;
$result["exception_method"] = $vsss->method;
}
}
}
ZMBuf::$events[MiddlewareClass::class]["\\".$reflection_class->getName()] = $result;
continue 2;
} }
} }
foreach ($methods as $vs) { foreach ($methods as $vs) {
@@ -74,8 +99,9 @@ class AnnotationParser
elseif ($vss instanceof CustomAnnotation) ZMBuf::$events[get_class($vss)][] = $vss; elseif ($vss instanceof CustomAnnotation) ZMBuf::$events[get_class($vss)][] = $vss;
elseif ($vss instanceof CQBefore) ZMBuf::$events[CQBefore::class][$vss->cq_event][] = $vss; elseif ($vss instanceof CQBefore) ZMBuf::$events[CQBefore::class][$vss->cq_event][] = $vss;
elseif ($vss instanceof CQAfter) ZMBuf::$events[CQAfter::class][$vss->cq_event][] = $vss; elseif ($vss instanceof CQAfter) ZMBuf::$events[CQAfter::class][$vss->cq_event][] = $vss;
elseif ($vss instanceof OnStart) { elseif ($vss instanceof OnStart) ZMBuf::$events[OnStart::class][] = $vss;
ZMBuf::$events[OnStart::class][]=$vss; elseif ($vss instanceof Middleware){
ZMBuf::$events[MiddlewareInterface::class][$vss->class][$vss->method] = $vss->middleware;
} }
} }
} }
@@ -84,7 +110,7 @@ class AnnotationParser
ZMBuf::$req_mapping = $tree[0]; ZMBuf::$req_mapping = $tree[0];
//给支持level的排个序 //给支持level的排个序
foreach (ZMBuf::$events as $class_name => $v) { foreach (ZMBuf::$events as $class_name => $v) {
if ((new $class_name()) instanceof Level) { if (is_a($class_name, Level::class, true)) {
for ($i = 0; $i < count(ZMBuf::$events[$class_name]) - 1; ++$i) { for ($i = 0; $i < count(ZMBuf::$events[$class_name]) - 1; ++$i) {
for ($j = 0; $j < count(ZMBuf::$events[$class_name]) - $i - 1; ++$j) { for ($j = 0; $j < count(ZMBuf::$events[$class_name]) - $i - 1; ++$j) {
$l1 = ZMBuf::$events[$class_name][$j]->level; $l1 = ZMBuf::$events[$class_name][$j]->level;
@@ -100,8 +126,7 @@ class AnnotationParser
} }
} }
private static function getRuleCallback($rule_str) private static function getRuleCallback($rule_str) {
{
$func = null; $func = null;
$rule = $rule_str; $rule = $rule_str;
if ($rule != "") { if ($rule != "") {
@@ -179,23 +204,20 @@ class AnnotationParser
return $func; return $func;
} }
private static function registerRuleEvent(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) private static function registerRuleEvent(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) {
{
$vss->callback = self::getRuleCallback($vss->getRule()); $vss->callback = self::getRuleCallback($vss->getRule());
$vss->method = $method->getName(); $vss->method = $method->getName();
$vss->class = $class->getName(); $vss->class = $class->getName();
return $vss; return $vss;
} }
private static function registerMethod(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) private static function registerMethod(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) {
{
$vss->method = $method->getName(); $vss->method = $method->getName();
$vss->class = $class->getName(); $vss->class = $class->getName();
return $vss; return $vss;
} }
private static function registerRequestMapping(RequestMapping $vss, ReflectionMethod $method, ReflectionClass $class, string $prefix) private static function registerRequestMapping(RequestMapping $vss, ReflectionMethod $method, ReflectionClass $class, string $prefix) {
{
$array = ZMBuf::$req_mapping; $array = ZMBuf::$req_mapping;
$uid = count($array); $uid = count($array);
$prefix_exp = explode("/", $prefix); $prefix_exp = explode("/", $prefix);
@@ -263,8 +285,7 @@ class AnnotationParser
ZMBuf::$req_mapping = $array; ZMBuf::$req_mapping = $array;
} }
private static function loadAnnotationClasses() private static function loadAnnotationClasses() {
{
$class = getAllClasses(WORKING_DIR . "/src/ZM/Annotation/", "ZM\\Annotation"); $class = getAllClasses(WORKING_DIR . "/src/ZM/Annotation/", "ZM\\Annotation");
foreach ($class as $v) { foreach ($class as $v) {
$s = WORKING_DIR . '/src/' . str_replace("\\", "/", $v) . ".php"; $s = WORKING_DIR . '/src/' . str_replace("\\", "/", $v) . ".php";
@@ -277,8 +298,7 @@ class AnnotationParser
} }
} }
public static function genTree($items) public static function genTree($items) {
{
$tree = array(); $tree = array();
foreach ($items as $item) foreach ($items as $item)
if (isset($items[$item['pid']])) if (isset($items[$item['pid']]))

View File

@@ -0,0 +1,19 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
/**
* Class After
* @package ZM\Annotation\Http
* @Annotation
* @Target("METHOD")
*/
class After extends AnnotationBase
{
}

View File

@@ -0,0 +1,19 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
/**
* Class Before
* @package ZM\Annotation\Http
* @Annotation
* @Target("METHOD")
*/
class Before extends AnnotationBase
{
}

View File

@@ -0,0 +1,23 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Target;
use Exception;
use ZM\Annotation\AnnotationBase;
/**
* Class HandleException
* @package ZM\Annotation\Http
* @Annotation
* @Target("METHOD")
*/
class HandleException extends AnnotationBase
{
/**
* @var string
*/
public $class_name = Exception::class;
}

View File

@@ -0,0 +1,24 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
/**
* Class Middleware
* @package ZM\Annotation\Http
* @Annotation
* @Target("METHOD")
*/
class Middleware extends AnnotationBase
{
/**
* @var string
* @Required()
*/
public $middleware;
}

View File

@@ -0,0 +1,19 @@
<?php
namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase;
/**
* Class MiddlewareClass
* @package ZM\Annotation\Http
* @Annotation
* @Target("CLASS")
*/
class MiddlewareClass extends AnnotationBase
{
}

View File

@@ -5,10 +5,13 @@ namespace ZM\Event\Swoole;
use Closure; use Closure;
use Exception;
use Framework\ZMBuf; use Framework\ZMBuf;
use Swoole\Http\Request; use Swoole\Http\Request;
use ZM\Annotation\Http\MiddlewareClass;
use ZM\Annotation\Swoole\SwooleEventAfter; use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt; use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Http\MiddlewareInterface;
use ZM\Http\Response; use ZM\Http\Response;
use ZM\ModBase; use ZM\ModBase;
use ZM\ModHandleType; use ZM\ModHandleType;
@@ -30,6 +33,10 @@ class RequestEvent implements SwooleEvent
$this->response = $response; $this->response = $response;
} }
/**
* @return $this|SwooleEvent
* @throws Exception
*/
public function onActivate() { public function onActivate() {
ZMUtil::checkWait(); ZMUtil::checkWait();
foreach (ZMBuf::globals("http_header") as $k => $v) { foreach (ZMBuf::globals("http_header") as $k => $v) {
@@ -82,14 +89,44 @@ class RequestEvent implements SwooleEvent
if (in_array(strtoupper($this->request->server["request_method"]), $node["request_method"] ?? [])) { //判断目标方法在不在里面 if (in_array(strtoupper($this->request->server["request_method"]), $node["request_method"] ?? [])) { //判断目标方法在不在里面
$c_name = $node["class"]; $c_name = $node["class"];
/** @var ModBase $class */ if (isset(ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]])) {
$class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST); $middleware = ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]];
$r = call_user_func_array([$class, $node["method"]], [$params]); $middleware = ZMBuf::$events[MiddlewareClass::class][$middleware];
if (is_string($r) && !$this->response->isEnd()) $this->response->end($r); $before = $middleware["class"];
if ($class->block_continue) return $this; $r = new $before();
if ($this->response->isEnd()) return $this; $before_result = true;
if (isset($middleware["before"])) {
$before_result = call_user_func([$r, $middleware["before"]], $this->request, $this->response, $params);
if ($before_result !== false) $before_result = true;
}
if ($before_result) {
try {
/** @var ModBase $class */
$class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST);
$result = call_user_func_array([$class, $node["method"]], [$params]);
if (is_string($result) && !$this->response->isEnd()) $this->response->end($result);
if (!$this->response->isEnd()) goto eventCall;
} catch (Exception $e) {
if (!isset($middleware["exception"])) throw $e;
if ($e instanceof $middleware["exception"]) {
call_user_func([$r, $middleware["exception_method"]], $e, $this->request, $this->response, $params);
return $this;
} else throw $e;
}
}
if (isset($middleware["after"])) {
call_user_func([$r, $middleware["after"]], $this->request, $this->response, $params);
return $this;
}
} else {
/** @var ModBase $class */
$class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST);
$r = call_user_func_array([$class, $node["method"]], [$params]);
if (is_string($r) && !$this->response->isEnd()) $this->response->end($r);
if (!$this->response->isEnd()) goto eventCall;
}
} }
eventCall:
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) { foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) { if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) {
$c = $v->class; $c = $v->class;
@@ -127,7 +164,7 @@ class RequestEvent implements SwooleEvent
} }
private function parseSwooleRule($v) { private function parseSwooleRule($v) {
switch (explode(":",$v->rule)[0]) { switch (explode(":", $v->rule)[0]) {
case "containsGet": case "containsGet":
case "containsPost": case "containsPost":
if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->request); if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->request);

View File

@@ -0,0 +1,10 @@
<?php
namespace ZM\Http;
interface MiddlewareInterface
{
}

View File

@@ -40,7 +40,7 @@ class DataProvider
return ZMBuf::globals("http_reverse_link"); return ZMBuf::globals("http_reverse_link");
} }
private static function getJsonData(string $string) { public static function getJsonData(string $string) {
if(!file_exists(self::getDataConfig().$string)) return []; if(!file_exists(self::getDataConfig().$string)) return [];
return json_decode(Co::readFile(self::getDataConfig().$string), true); return json_decode(Co::readFile(self::getDataConfig().$string), true);
} }