update to 2.1.5 version

change route to Symfony routing
This commit is contained in:
crazywhalecc
2021-01-13 15:40:27 +08:00
parent ccadec23e4
commit 1ef8225d10
7 changed files with 91 additions and 162 deletions

View File

@@ -3,7 +3,7 @@
"description": "High performance QQ robot and web server development framework",
"minimum-stability": "stable",
"license": "Apache-2.0",
"version": "2.1.4",
"version": "2.1.5",
"extra": {
"exclude_annotate": [
"src/ZM"

View File

@@ -12,6 +12,7 @@ use ReflectionMethod;
use ZM\Annotation\Http\{HandleAfter, HandleBefore, Controller, HandleException, Middleware, MiddlewareClass, RequestMapping};
use ZM\Annotation\Interfaces\Level;
use ZM\Annotation\Module\Closed;
use ZM\Http\RouteManager;
use ZM\Utils\DataProvider;
class AnnotationParser
@@ -113,7 +114,7 @@ class AnnotationParser
$method_anno->class = $v;
$method_anno->method = $method_name;
if ($method_anno instanceof RequestMapping) {
$this->registerRequestMapping($method_anno, $method_name, $v, $methods_annotations); //TODO: 用symfony的routing重写
RouteManager::importRouteByAnnotation($method_anno, $method_name, $v, $methods_annotations);
} elseif ($method_anno instanceof Middleware) {
$this->middleware_map[$method_anno->class][$method_anno->method][] = $method_anno->middleware;
}
@@ -121,11 +122,6 @@ class AnnotationParser
}
}
}
//预处理4生成路由树换成symfony后就不需要了
$tree = $this->genTree($this->req_mapping);
$this->req_mapping = $tree[0];
Console::debug("解析注解完毕!");
}
@@ -175,109 +171,6 @@ class AnnotationParser
//private function below
private function registerRequestMapping(RequestMapping $vss, $method, $class, $methods_annotations) {
$prefix = '';
foreach ($methods_annotations as $annotation) {
if ($annotation instanceof Controller) {
$prefix = $annotation->prefix;
break;
}
}
$array = $this->req_mapping;
$uid = count($array);
$prefix_exp = explode("/", $prefix);
$route_exp = explode("/", $vss->route);
foreach ($prefix_exp as $k => $v) {
if ($v == "" || $v == ".." || $v == ".") {
unset($prefix_exp[$k]);
}
}
foreach ($route_exp as $k => $v) {
if ($v == "" || $v == ".." || $v == ".") {
unset($route_exp[$k]);
}
}
if ($prefix_exp == [] && $route_exp == []) {
$array[0]['method'] = $method;
$array[0]['class'] = $class;
$array[0]['request_method'] = $vss->request_method;
$array[0]['route'] = $vss->route;
$this->req_mapping = $array;
return;
}
$pid = 0;
while (($shift = array_shift($prefix_exp)) !== null) {
foreach ($array as $k => $v) {
if ($v["name"] == $shift && $pid == ($v["pid"] ?? -1)) {
$pid = $v["id"];
continue 2;
}
}
$array[$uid++] = [
'id' => $uid - 1,
'pid' => $pid,
'name' => $shift
];
$pid = $uid - 1;
}
while (($shift = array_shift($route_exp)) !== null) {
/*if (mb_substr($shift, 0, 1) == "{" && mb_substr($shift, -1, 1) == "}") {
$p->removeAllRoute();
Console::info("移除本节点其他所有路由中");
}*/
foreach ($array as $k => $v) {
if ($v["name"] == $shift && $pid == ($v["pid"] ?? -1)) {
$pid = $v["id"];
continue 2;
}
}
if (mb_substr($shift, 0, 1) == "{" && mb_substr($shift, -1, 1) == "}") {
foreach ($array as $k => $v) {
if ($pid == $v["id"]) {
$array[$k]["param_route"] = $uid;
}
}
}
$array[$uid++] = [
'id' => $uid - 1,
'pid' => $pid,
'name' => $shift
];
$pid = $uid - 1;
}
$array[$uid - 1]['method'] = $method;
$array[$uid - 1]['class'] = $class;
$array[$uid - 1]['request_method'] = $vss->request_method;
$array[$uid - 1]['route'] = $vss->route;
$this->req_mapping = $array;
}
/** @noinspection PhpIncludeInspection */
private function loadAnnotationClasses() {
$class = getAllClasses(WORKING_DIR . "/src/ZM/Annotation/", "ZM\\Annotation");
foreach ($class as $v) {
$s = WORKING_DIR . '/src/' . str_replace("\\", "/", $v) . ".php";
//Console::debug("Requiring annotation " . $s);
require_once $s;
}
$class = getAllClasses(DataProvider::getWorkingDir() . "/src/Custom/Annotation/", "Custom\\Annotation");
foreach ($class as $v) {
$s = DataProvider::getWorkingDir() . '/src/' . str_replace("\\", "/", $v) . ".php";
Console::debug("Requiring custom annotation " . $s);
require_once $s;
}
}
private function genTree($items) {
$tree = array();
foreach ($items as $item)
if (isset($items[$item['pid']]))
$items[$item['pid']]['son'][] = &$items[$item['id']];
else
$tree[] = &$items[$item['id']];
return $tree;
}
private function registerMiddleware(MiddlewareClass $vs, ReflectionClass $reflection_class) {
$result = [
"class" => "\\" . $reflection_class->getName(),

View File

@@ -301,7 +301,7 @@ class ServerEventHandler
* @param $request
* @param $response
*/
public function onRequest($request, $response) {
public function onRequest(?Request $request, ?\Swoole\Http\Response $response) {
$response = new Response($response);
unset(Context::$context[Co::getCid()]);
Console::debug("Calling Swoole \"request\" event from fd=" . $request->fd);

View File

@@ -280,8 +280,8 @@ class Framework
}
break;
default:
Console::info("Calculating ".$x);
dump($y);
//Console::info("Calculating ".$x);
//dump($y);
break;
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace ZM\Http;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use ZM\Annotation\Http\Controller;
use ZM\Annotation\Http\RequestMapping;
class RouteManager
{
/** @var null|RouteCollection */
public static $routes = null;
public static function importRouteByAnnotation(RequestMapping $vss, $method, $class, $methods_annotations) {
if(self::$routes === null) self::$routes = new RouteCollection();
// 拿到所属方法的类上面有没有控制器的注解
$prefix = '';
foreach ($methods_annotations as $annotation) {
if ($annotation instanceof Controller) {
$prefix = $annotation->prefix;
break;
}
}
$route_name = $prefix."/".$vss->route;
$route = new Route($route_name, ['_class' => $class, '_method' => $method]);
$route->setMethods($vss->request_method);
self::$routes->add(md5($route_name), $route);
}
}

View File

@@ -5,57 +5,47 @@ namespace ZM\Utils;
use Co;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use ZM\Config\ZMConfig;
use ZM\Console\Console;
use ZM\Event\EventManager;
use ZM\Http\Response;
use ZM\Http\RouteManager;
class HttpUtil
{
public static function parseUri($request, $response, $uri, &$node, &$params) {
$uri = explode("/", $uri);
$uri = array_diff($uri, ["..", "", "."]);
$node = EventManager::$req_mapping;
$params = [];
while (true) {
$r = array_shift($uri);
if ($r === null) break;
if (($cnt = count($node["son"] ?? [])) == 1) {
if (isset($node["param_route"])) {
foreach ($node["son"] as $k => $v) {
if ($v["id"] == $node["param_route"]) {
$node = $v;
$params[mb_substr($v["name"], 1, -1)] = $r;
continue 2;
}
}
} elseif ($node["son"][0]["name"] == $r) {
$node = $node["son"][0];
continue;
}
} elseif ($cnt >= 1) {
if (isset($node["param_route"])) {
foreach ($node["son"] as $k => $v) {
if ($v["id"] == $node["param_route"]) {
$node = $v;
$params[mb_substr($v["name"], 1, -1)] = $r;
continue 2;
}
}
}
foreach ($node["son"] as $k => $v) {
if ($v["name"] == $r) {
$node = $v;
continue 2;
}
}
}
$context = new RequestContext();
$context->setMethod($request->server['request_method']);
try {
$matcher = new UrlMatcher(RouteManager::$routes ?? new RouteCollection(), $context);
$matched = $matcher->match($uri);
} catch (ResourceNotFoundException $e) {
if (ZMConfig::get("global", "static_file_server")["status"]) {
HttpUtil::handleStaticPage($request->server["request_uri"], $response);
return null;
}
$matched = null;
} catch (MethodNotAllowedException $e) {
$matched = null;
}
if ($matched !== null) {
$node = [
"route" => RouteManager::$routes->get($matched["_route"])->getPath(),
"class" => $matched["_class"],
"method" => $matched["_method"],
"request_method" => $request->server['request_method']
];
unset($matched["_class"], $matched["_method"]);
$params = $matched;
return true;
} else {
return false;
}
return !isset($node["route"]) ? false : true;
}
public static function getHttpCodePage(int $http_code) {
@@ -83,9 +73,9 @@ class HttpUtil
return true;
}
if (is_dir($path)) {
if(mb_substr($uri, -1, 1) != "/") {
if (mb_substr($uri, -1, 1) != "/") {
Console::info("[302] " . $uri);
$response->redirect($uri."/", 302);
$response->redirect($uri . "/", 302);
return true;
}
foreach ($base_index as $vp) {

View File

@@ -2,13 +2,17 @@
require __DIR__ . "/../vendor/autoload.php";
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
$root = new RouteCollection();
$route = new Route('/foo', array('controller' => 'MyController'));
$routes = new RouteCollection();
$routes->add('route_name', $route);
@@ -35,30 +39,37 @@ $routes->add('date', new Route(
array() // methods
));
$route = new Route('/archive/test');
$routes->add('qwerty', $route);
$route = new Route('/');
$route = new Route('/{aas}/{test}', ['_class' => stdClass::class, '_method' => 'foo'],[],["class" => stdClass::class]);
$routes->add('root', $route);
$context = new RequestContext();
$matcher = new UrlMatcher($routes, $context);
//$root->addCollection($routes);
$matcher = new UrlMatcher($root, $context);
$root->addCollection($routes);
dump($root->all());
//$parameters = $matcher->match('/test/foo');var_dump($parameters);
$parameters = $matcher->match('/archive/2012-01');
var_dump($parameters);
// array(
// 'controller' => 'showArchive',
// 'month' => '2012-01',
// 'subdomain' => 'www',
// '_route' => ...
// )
try {
$parameters = $matcher->match('/fooss/%20');
var_dump($parameters);
} catch (ResourceNotFoundException $e) {
echo $e->getMessage().PHP_EOL;
} catch (MethodNotAllowedException $e) {
}
$parameters = $matcher->match('/');
var_dump($parameters);
$sub = new RouteCollection();