From 8f288dd134e51318bf29343293a436f5f756ac87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Thu, 4 Nov 2021 17:16:40 +0800 Subject: [PATCH 01/18] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E5=92=8C=E6=8F=92=E4=BB=B6=E6=8E=A5=E5=8F=A3=E8=A6=86=E7=9B=96?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Http/RouteCollection.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Http/RouteCollection.php b/src/Http/RouteCollection.php index 063e7c0..afa7ae2 100644 --- a/src/Http/RouteCollection.php +++ b/src/Http/RouteCollection.php @@ -48,9 +48,9 @@ class RouteCollection $this->currentGroupPrefix = ''; } - public function get($path, $name, $handler) + public function get($path, $name, $handler,$replaceHandler = null) { - return $this->addRoute('GET', $path, $name, $handler); + return $this->addRoute('GET', $path, $name, $handler,$replaceHandler); } public function post($path, $name, $handler) @@ -73,7 +73,13 @@ class RouteCollection return $this->addRoute('DELETE', $path, $name, $handler); } - public function group($prefix, callable $callback) + /** + * @param $prefix + * @param callable $callback + * @param int $times 访问次数 + * @param int $interval 时间间隔(秒) + */ + public function group($prefix, callable $callback, $times = 100, $interval = 60) { $previousGroupPrefix = $this->currentGroupPrefix; $this->currentGroupPrefix = $previousGroupPrefix . $prefix; @@ -81,7 +87,7 @@ class RouteCollection $this->currentGroupPrefix = $previousGroupPrefix; } - public function addRoute($method, $path, $name, $handler) + public function addRoute($method, $path, $name, $handler,$replaceHandler = null) { $path = $this->currentGroupPrefix . $path; $path = str_replace('//','/',$path); -- Gitee From f3d648ccc4f5d34db781ac1c6b8d00c04cb292c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Thu, 4 Nov 2021 17:23:29 +0800 Subject: [PATCH 02/18] no message --- src/Http/RouteCollection.php | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Http/RouteCollection.php b/src/Http/RouteCollection.php index afa7ae2..ede55cc 100644 --- a/src/Http/RouteCollection.php +++ b/src/Http/RouteCollection.php @@ -48,9 +48,9 @@ class RouteCollection $this->currentGroupPrefix = ''; } - public function get($path, $name, $handler,$replaceHandler = null) + public function get($path, $name, $handler, $replaceHandler = null) { - return $this->addRoute('GET', $path, $name, $handler,$replaceHandler); + return $this->addRoute('GET', $path, $name, $handler, $replaceHandler); } public function post($path, $name, $handler) @@ -73,24 +73,31 @@ class RouteCollection return $this->addRoute('DELETE', $path, $name, $handler); } + public function group($prefix, callable $callback) + { + $previousGroupPrefix = $this->currentGroupPrefix; + $this->currentGroupPrefix = $previousGroupPrefix . $prefix; + $callback($this); + $this->currentGroupPrefix = $previousGroupPrefix; + } + /** - * @param $prefix * @param callable $callback * @param int $times 访问次数 * @param int $interval 时间间隔(秒) */ - public function group($prefix, callable $callback, $times = 100, $interval = 60) + public function withFrequency(callable $callback, $times = 100, $interval = 60) { $previousGroupPrefix = $this->currentGroupPrefix; - $this->currentGroupPrefix = $previousGroupPrefix . $prefix; + $this->currentGroupPrefix = $previousGroupPrefix; $callback($this); $this->currentGroupPrefix = $previousGroupPrefix; } - public function addRoute($method, $path, $name, $handler,$replaceHandler = null) + public function addRoute($method, $path, $name, $handler, $replaceHandler = null) { $path = $this->currentGroupPrefix . $path; - $path = str_replace('//','/',$path); + $path = str_replace('//', '/', $path); $routeDatas = $this->routeParser->parse($path); foreach ($routeDatas as $routeData) { $this->dataGenerator->addRoute($method, $routeData, $handler); @@ -117,7 +124,7 @@ class RouteCollection if (isset($this->reverse[$name])) { $parts = $this->reverse[$name][0]; array_walk($parts, [$this, 'fixPathPart'], $parameters); - return '/'.ltrim(implode('', $parts), '/'); + return '/' . ltrim(implode('', $parts), '/'); } throw new \RuntimeException("Route $name not found"); } -- Gitee From 71bed8f076cad91fce47e0b5e3df765687818f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Fri, 5 Nov 2021 14:56:10 +0800 Subject: [PATCH 03/18] no message --- src/Api/ApiServiceProvider.php | 34 ++--- src/Common/Utils.php | 7 +- src/Http/GroupCountBased.php | 48 ++++++ src/Http/Middleware/DispatchRoute.php | 5 + src/Http/RegexBasedAbstract.php | 203 ++++++++++++++++++++++++++ src/Http/RouteCollection.php | 33 +++-- 6 files changed, 294 insertions(+), 36 deletions(-) create mode 100644 src/Http/GroupCountBased.php create mode 100644 src/Http/RegexBasedAbstract.php diff --git a/src/Api/ApiServiceProvider.php b/src/Api/ApiServiceProvider.php index eeaa666..ce23e1c 100644 --- a/src/Api/ApiServiceProvider.php +++ b/src/Api/ApiServiceProvider.php @@ -130,33 +130,33 @@ class ApiServiceProvider extends ServiceProvider require $this->app->basePath('routes/api.php'); }); } else if ($this->matchPrefix($reqUri, $pluginApiPrefix)) { - $this->setPluginRoutes($route, $pluginName); +// $this->setPluginRoutes($route,$plugins, $pluginName); } else { $route->group($userApiPrefix, function (RouteCollection $route) { require $this->app->basePath('routes/api.php'); }); } + $plugins = \Discuz\Common\Utils::getPluginList(); + //加载插件所有接口 + $this->setPluginRoutes($route, $plugins, $pluginName); } - private function setPluginRoutes(RouteCollection $route, $pluginName) + private function setPluginRoutes(RouteCollection $route, $plugins, $pluginName) { - $plugins = \Discuz\Common\Utils::getPluginList(); - $plugin = array_filter($plugins, function ($item) use ($pluginName) { - return strtolower($item['name_en']) == strtolower($pluginName); - }); - $plugin = current($plugin); - if (empty($plugin)) exit('plugin ' . $pluginName . ' not exist.'); - $prefix = '/plugin/' . $plugin['name_en'] . '/api/'; - $route->group($prefix, function (RouteCollection $route) use ($plugin) { - $pluginFiles = $plugin['plugin_' . $plugin['app_id']]; - Utils::setPluginAppId($plugin['app_id']); - if (isset($pluginFiles['routes'])) { - foreach ($pluginFiles['routes'] as $routeFile) { - require_once $routeFile; + foreach ($plugins as $plugin) { + if (empty($plugin)) exit('plugin ' . $pluginName . ' not exist.'); + $prefix = '/plugin/' . $plugin['name_en'] . '/api/'; + $route->group($prefix, function (RouteCollection $route) use ($plugin) { + $pluginFiles = $plugin['plugin_' . $plugin['app_id']]; + Utils::setPluginAppId($plugin['app_id']); + if (isset($pluginFiles['routes'])) { + foreach ($pluginFiles['routes'] as $routeFile) { + require_once $routeFile; + } } - } - }); + }); + } } private function matchPrefix($uri, $prefix) diff --git a/src/Common/Utils.php b/src/Common/Utils.php index 2d4f969..32bd957 100644 --- a/src/Common/Utils.php +++ b/src/Common/Utils.php @@ -193,8 +193,8 @@ class Utils public static function getPluginList() { - $cacheConfig = DzqCache::get(CacheKey::PLUGIN_LOCAL_CONFIG); - if ($cacheConfig) return $cacheConfig; +// $cacheConfig = DzqCache::get(CacheKey::PLUGIN_LOCAL_CONFIG); +// if ($cacheConfig) return $cacheConfig; $pluginDir = base_path('plugin'); $directories = Finder::create()->in($pluginDir)->directories()->depth(0)->sortByName(); $plugins = []; @@ -215,7 +215,8 @@ class Utils $routeFiles = Finder::create()->in($routesPath)->path('/.*\.php/')->files(); $routesPath = []; foreach ($routeFiles as $routeFile) { - $routesPath[] = $routeFile->getPathname(); + $routePath = $routeFile->getPathname(); + $routesPath[] = $routePath; } } else { if ($filename == 'config') { diff --git a/src/Http/GroupCountBased.php b/src/Http/GroupCountBased.php new file mode 100644 index 0000000..4fbe7d4 --- /dev/null +++ b/src/Http/GroupCountBased.php @@ -0,0 +1,48 @@ + $route) { + $numVariables = count($route->variables); + $numGroups = max($numGroups, $numVariables); + + $regexes[] = $regex . str_repeat('()', $numGroups - $numVariables); + $routeMap[$numGroups + 1] = [$route->handler, $route->variables]; + + ++$numGroups; + } + + $regex = '~^(?|' . implode('|', $regexes) . ')$~'; + return ['regex' => $regex, 'routeMap' => $routeMap]; + } +} + diff --git a/src/Http/Middleware/DispatchRoute.php b/src/Http/Middleware/DispatchRoute.php index b145e1d..204b356 100644 --- a/src/Http/Middleware/DispatchRoute.php +++ b/src/Http/Middleware/DispatchRoute.php @@ -20,6 +20,7 @@ namespace Discuz\Http\Middleware; use Discuz\Http\Exception\MethodNotAllowedException; use Discuz\Http\Exception\RouteNotFoundException; +use Discuz\Http\GroupCountBased; use Discuz\Http\RouteCollection; use Discuz\Http\RouteHandlerFactory; use Psr\Http\Message\ResponseInterface; @@ -65,6 +66,7 @@ class DispatchRoute implements MiddlewareInterface { $method = $request->getMethod(); $uri = $request->getUri()->getPath() ?: '/'; + dd('gxxx',$this->getDispatcher()); $routeInfo = $this->getDispatcher()->dispatch($method, $uri); switch ($routeInfo[0]) { case Dispatcher::NOT_FOUND: @@ -82,6 +84,9 @@ class DispatchRoute implements MiddlewareInterface { if (! isset($this->dispatcher)) { $this->dispatcher = new Dispatcher\GroupCountBased($this->routes->getRouteData()); + $d = $this->routes->getRouteData(); + $this->dispatcher = new \Discuz\Http\GroupCountBased($d); + } return $this->dispatcher; } diff --git a/src/Http/RegexBasedAbstract.php b/src/Http/RegexBasedAbstract.php new file mode 100644 index 0000000..446f75f --- /dev/null +++ b/src/Http/RegexBasedAbstract.php @@ -0,0 +1,203 @@ +isStaticRoute($routeData)) { + $this->addStaticRoute($httpMethod, $routeData, $handler,$replaceHandler); + } else { + $this->addVariableRoute($httpMethod, $routeData, $handler,$replaceHandler); + } + } + + /** + * @return mixed[] + */ + public function getData() + { + if (empty($this->methodToRegexToRoutesMap)) { + return [$this->staticRoutes, []]; + } + + return [$this->staticRoutes, $this->generateVariableRouteData()]; + } + + /** + * @return mixed[] + */ + private function generateVariableRouteData() + { + $data = []; + foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) { + $chunkSize = $this->computeChunkSize(count($regexToRoutesMap)); + $chunks = array_chunk($regexToRoutesMap, $chunkSize, true); + $data[$method] = array_map([$this, 'processChunk'], $chunks); + } + return $data; + } + + /** + * @param int + * @return int + */ + private function computeChunkSize($count) + { + $numParts = max(1, round($count / $this->getApproxChunkSize())); + return (int) ceil($count / $numParts); + } + + /** + * @param mixed[] + * @return bool + */ + private function isStaticRoute($routeData) + { + return count($routeData) === 1 && is_string($routeData[0]); + } + + private function addStaticRoute($httpMethod, $routeData, $handler,$replaceHandler = null) + { + $routeStr = $routeData[0]; + + if (isset($this->staticRoutes[$httpMethod][$routeStr])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $routeStr, $httpMethod + )); + } + + if (isset($this->methodToRegexToRoutesMap[$httpMethod])) { + foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) { + if ($route->matches($routeStr)) { + throw new BadRouteException(sprintf( + 'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"', + $routeStr, $route->regex, $httpMethod + )); + } + } + } + + $this->staticRoutes[$httpMethod][$routeStr] = [$handler,$replaceHandler]; +// $this->staticRoutes[$httpMethod][$routeStr] = $handler; + } + + private function addVariableRoute($httpMethod, $routeData, $handler,$replaceHandler = null) + { + list($regex, $variables) = $this->buildRegexForRoute($routeData); + + if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) { + throw new BadRouteException(sprintf( + 'Cannot register two routes matching "%s" for method "%s"', + $regex, $httpMethod + )); + } + + $this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route( + $httpMethod, $handler, $regex, $variables + ); + } + + /** + * @param mixed[] + * @return mixed[] + */ + private function buildRegexForRoute($routeData) + { + $regex = ''; + $variables = []; + foreach ($routeData as $part) { + if (is_string($part)) { + $regex .= preg_quote($part, '~'); + continue; + } + + list($varName, $regexPart) = $part; + + if (isset($variables[$varName])) { + throw new BadRouteException(sprintf( + 'Cannot use the same placeholder "%s" twice', $varName + )); + } + + if ($this->regexHasCapturingGroups($regexPart)) { + throw new BadRouteException(sprintf( + 'Regex "%s" for parameter "%s" contains a capturing group', + $regexPart, $varName + )); + } + + $variables[$varName] = $varName; + $regex .= '(' . $regexPart . ')'; + } + + return [$regex, $variables]; + } + + /** + * @param string + * @return bool + */ + private function regexHasCapturingGroups($regex) + { + if (false === strpos($regex, '(')) { + // Needs to have at least a ( to contain a capturing group + return false; + } + + // Semi-accurate detection for capturing groups + return (bool) preg_match( + '~ + (?: + \(\?\( + | \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \] + | \\\\ . + ) (*SKIP)(*FAIL) | + \( + (?! + \? (?! <(?![!=]) | P< | \' ) + | \* + ) + ~x', + $regex + ); + } +} + diff --git a/src/Http/RouteCollection.php b/src/Http/RouteCollection.php index ede55cc..665d8c7 100644 --- a/src/Http/RouteCollection.php +++ b/src/Http/RouteCollection.php @@ -42,7 +42,8 @@ class RouteCollection public function __construct() { - $this->dataGenerator = new DataGenerator\GroupCountBased; + $this->dataGenerator = new GroupCountBased(); + $this->routeParser = new RouteParser\Std; $this->currentGroupPrefix = ''; @@ -58,20 +59,20 @@ class RouteCollection return $this->addRoute('POST', $path, $name, $handler); } - public function put($path, $name, $handler) - { - return $this->addRoute('PUT', $path, $name, $handler); - } - - public function patch($path, $name, $handler) - { - return $this->addRoute('PATCH', $path, $name, $handler); - } - - public function delete($path, $name, $handler) - { - return $this->addRoute('DELETE', $path, $name, $handler); - } +// public function put($path, $name, $handler) +// { +// return $this->addRoute('PUT', $path, $name, $handler); +// } +// +// public function patch($path, $name, $handler) +// { +// return $this->addRoute('PATCH', $path, $name, $handler); +// } +// +// public function delete($path, $name, $handler) +// { +// return $this->addRoute('DELETE', $path, $name, $handler); +// } public function group($prefix, callable $callback) { @@ -100,7 +101,7 @@ class RouteCollection $path = str_replace('//', '/', $path); $routeDatas = $this->routeParser->parse($path); foreach ($routeDatas as $routeData) { - $this->dataGenerator->addRoute($method, $routeData, $handler); + $this->dataGenerator->addRoute($method, $routeData, $handler,$replaceHandler); } $this->reverse[$name] = $routeDatas; -- Gitee From fdca44e40ed0f143347ec4086b115a160311419d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Sat, 6 Nov 2021 22:03:01 +0800 Subject: [PATCH 04/18] =?UTF-8?q?=E4=BF=AE=E6=94=B9GroupCountBased=20Regex?= =?UTF-8?q?BasedAbstract?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Http/GroupCountBased.php | 45 +++--- src/Http/Middleware/DispatchRoute.php | 25 +++- src/Http/RegexBasedAbstract.php | 203 +++++++------------------- src/Http/RouteCollection.php | 5 +- 4 files changed, 101 insertions(+), 177 deletions(-) diff --git a/src/Http/GroupCountBased.php b/src/Http/GroupCountBased.php index 4fbe7d4..87c1222 100644 --- a/src/Http/GroupCountBased.php +++ b/src/Http/GroupCountBased.php @@ -17,32 +17,41 @@ namespace Discuz\Http; -use FastRoute\Dispatcher\RegexBasedAbstract; -class GroupCountBased extends \Discuz\Http\RegexBasedAbstract +class GroupCountBased extends RegexBasedAbstract { - protected function getApproxChunkSize() + public function __construct($data) { - return 10; + list($this->staticRouteMap, $this->variableRouteData) = $data; } - protected function processChunk($regexToRoutesMap) + protected function dispatchVariableRoute($routeData, $uri) { - $routeMap = []; - $regexes = []; - $numGroups = 0; - foreach ($regexToRoutesMap as $regex => $route) { - $numVariables = count($route->variables); - $numGroups = max($numGroups, $numVariables); + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + + list($handler, $varNames) = $data['routeMap'][count($matches)]; + + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return [self::FOUND, $handler, $vars]; + } - $regexes[] = $regex . str_repeat('()', $numGroups - $numVariables); - $routeMap[$numGroups + 1] = [$route->handler, $route->variables]; + return [self::NOT_FOUND]; + } - ++$numGroups; - } + public function getStaticRouteMap() + { + return $this->staticRouteMap; + } - $regex = '~^(?|' . implode('|', $regexes) . ')$~'; - return ['regex' => $regex, 'routeMap' => $routeMap]; + public function getVariableRouteData() + { + return $this->variableRouteData; } } - diff --git a/src/Http/Middleware/DispatchRoute.php b/src/Http/Middleware/DispatchRoute.php index 204b356..8952e93 100644 --- a/src/Http/Middleware/DispatchRoute.php +++ b/src/Http/Middleware/DispatchRoute.php @@ -66,7 +66,6 @@ class DispatchRoute implements MiddlewareInterface { $method = $request->getMethod(); $uri = $request->getUri()->getPath() ?: '/'; - dd('gxxx',$this->getDispatcher()); $routeInfo = $this->getDispatcher()->dispatch($method, $uri); switch ($routeInfo[0]) { case Dispatcher::NOT_FOUND: @@ -76,18 +75,32 @@ class DispatchRoute implements MiddlewareInterface case Dispatcher::FOUND: $handler = $routeInfo[1]; $parameters = $routeInfo[2]; + $hMap = $this->getReplaceHandlersMap(); + $handler = $hMap[$handler]??$handler; return $this->factory->toController($handler)($request, $parameters); } } protected function getDispatcher() { - if (! isset($this->dispatcher)) { - $this->dispatcher = new Dispatcher\GroupCountBased($this->routes->getRouteData()); - $d = $this->routes->getRouteData(); - $this->dispatcher = new \Discuz\Http\GroupCountBased($d); - + if (!isset($this->dispatcher)) { + $this->dispatcher = new GroupCountBased($this->routes->getRouteData()); } return $this->dispatcher; } + protected function getReplaceHandlersMap(){ + $dispatcher = $this->getDispatcher(); + $staticRouteMap = $dispatcher->getStaticRouteMap(); +// $variableRouteData = $dispatcher->getVariableRouteData(); + $hMap = []; + foreach ($staticRouteMap as $staticRoutes) { + foreach ($staticRoutes as $staticRoute) { + if(strpos($staticRoute,'|')){ + $handlers = explode('|',$staticRoute); + $hMap[$handlers[1]] = $handlers[0]; + } + } + } + return $hMap; + } } diff --git a/src/Http/RegexBasedAbstract.php b/src/Http/RegexBasedAbstract.php index 446f75f..86657f3 100644 --- a/src/Http/RegexBasedAbstract.php +++ b/src/Http/RegexBasedAbstract.php @@ -17,187 +17,88 @@ namespace Discuz\Http; -use FastRoute\BadRouteException; -use FastRoute\DataGenerator; -use FastRoute\Route; -abstract class RegexBasedAbstract implements DataGenerator +use FastRoute\Dispatcher; + +abstract class RegexBasedAbstract implements Dispatcher { /** @var mixed[][] */ - protected $staticRoutes = []; - - /** @var Route[][] */ - protected $methodToRegexToRoutesMap = []; + protected $staticRouteMap = []; - /** - * @return int - */ - abstract protected function getApproxChunkSize(); + /** @var mixed[] */ + protected $variableRouteData = []; /** * @return mixed[] */ - abstract protected function processChunk($regexToRoutesMap); + abstract protected function dispatchVariableRoute($routeData, $uri); - public function addRoute($httpMethod, $routeData, $handler,$replaceHandler=null) + public function dispatch($httpMethod, $uri) { - if ($this->isStaticRoute($routeData)) { - $this->addStaticRoute($httpMethod, $routeData, $handler,$replaceHandler); - } else { - $this->addVariableRoute($httpMethod, $routeData, $handler,$replaceHandler); + if (isset($this->staticRouteMap[$httpMethod][$uri])) { + $handler = $this->staticRouteMap[$httpMethod][$uri]; + return [self::FOUND, $handler, []]; } - } - /** - * @return mixed[] - */ - public function getData() - { - if (empty($this->methodToRegexToRoutesMap)) { - return [$this->staticRoutes, []]; + $varRouteData = $this->variableRouteData; + if (isset($varRouteData[$httpMethod])) { + $result = $this->dispatchVariableRoute($varRouteData[$httpMethod], $uri); + if ($result[0] === self::FOUND) { + return $result; + } } - return [$this->staticRoutes, $this->generateVariableRouteData()]; - } - - /** - * @return mixed[] - */ - private function generateVariableRouteData() - { - $data = []; - foreach ($this->methodToRegexToRoutesMap as $method => $regexToRoutesMap) { - $chunkSize = $this->computeChunkSize(count($regexToRoutesMap)); - $chunks = array_chunk($regexToRoutesMap, $chunkSize, true); - $data[$method] = array_map([$this, 'processChunk'], $chunks); + // For HEAD requests, attempt fallback to GET + if ($httpMethod === 'HEAD') { + if (isset($this->staticRouteMap['GET'][$uri])) { + $handler = $this->staticRouteMap['GET'][$uri]; + return [self::FOUND, $handler, []]; + } + if (isset($varRouteData['GET'])) { + $result = $this->dispatchVariableRoute($varRouteData['GET'], $uri); + if ($result[0] === self::FOUND) { + return $result; + } + } } - return $data; - } - - /** - * @param int - * @return int - */ - private function computeChunkSize($count) - { - $numParts = max(1, round($count / $this->getApproxChunkSize())); - return (int) ceil($count / $numParts); - } - - /** - * @param mixed[] - * @return bool - */ - private function isStaticRoute($routeData) - { - return count($routeData) === 1 && is_string($routeData[0]); - } - private function addStaticRoute($httpMethod, $routeData, $handler,$replaceHandler = null) - { - $routeStr = $routeData[0]; - - if (isset($this->staticRoutes[$httpMethod][$routeStr])) { - throw new BadRouteException(sprintf( - 'Cannot register two routes matching "%s" for method "%s"', - $routeStr, $httpMethod - )); + // If nothing else matches, try fallback routes + if (isset($this->staticRouteMap['*'][$uri])) { + $handler = $this->staticRouteMap['*'][$uri]; + return [self::FOUND, $handler, []]; } - - if (isset($this->methodToRegexToRoutesMap[$httpMethod])) { - foreach ($this->methodToRegexToRoutesMap[$httpMethod] as $route) { - if ($route->matches($routeStr)) { - throw new BadRouteException(sprintf( - 'Static route "%s" is shadowed by previously defined variable route "%s" for method "%s"', - $routeStr, $route->regex, $httpMethod - )); - } + if (isset($varRouteData['*'])) { + $result = $this->dispatchVariableRoute($varRouteData['*'], $uri); + if ($result[0] === self::FOUND) { + return $result; } } - $this->staticRoutes[$httpMethod][$routeStr] = [$handler,$replaceHandler]; -// $this->staticRoutes[$httpMethod][$routeStr] = $handler; - } - - private function addVariableRoute($httpMethod, $routeData, $handler,$replaceHandler = null) - { - list($regex, $variables) = $this->buildRegexForRoute($routeData); + // Find allowed methods for this URI by matching against all other HTTP methods as well + $allowedMethods = []; - if (isset($this->methodToRegexToRoutesMap[$httpMethod][$regex])) { - throw new BadRouteException(sprintf( - 'Cannot register two routes matching "%s" for method "%s"', - $regex, $httpMethod - )); + foreach ($this->staticRouteMap as $method => $uriMap) { + if ($method !== $httpMethod && isset($uriMap[$uri])) { + $allowedMethods[] = $method; + } } - $this->methodToRegexToRoutesMap[$httpMethod][$regex] = new Route( - $httpMethod, $handler, $regex, $variables - ); - } - - /** - * @param mixed[] - * @return mixed[] - */ - private function buildRegexForRoute($routeData) - { - $regex = ''; - $variables = []; - foreach ($routeData as $part) { - if (is_string($part)) { - $regex .= preg_quote($part, '~'); + foreach ($varRouteData as $method => $routeData) { + if ($method === $httpMethod) { continue; } - list($varName, $regexPart) = $part; - - if (isset($variables[$varName])) { - throw new BadRouteException(sprintf( - 'Cannot use the same placeholder "%s" twice', $varName - )); + $result = $this->dispatchVariableRoute($routeData, $uri); + if ($result[0] === self::FOUND) { + $allowedMethods[] = $method; } - - if ($this->regexHasCapturingGroups($regexPart)) { - throw new BadRouteException(sprintf( - 'Regex "%s" for parameter "%s" contains a capturing group', - $regexPart, $varName - )); - } - - $variables[$varName] = $varName; - $regex .= '(' . $regexPart . ')'; } - return [$regex, $variables]; - } - - /** - * @param string - * @return bool - */ - private function regexHasCapturingGroups($regex) - { - if (false === strpos($regex, '(')) { - // Needs to have at least a ( to contain a capturing group - return false; + // If there are no allowed methods the route simply does not exist + if ($allowedMethods) { + return [self::METHOD_NOT_ALLOWED, $allowedMethods]; } - // Semi-accurate detection for capturing groups - return (bool) preg_match( - '~ - (?: - \(\?\( - | \[ [^\]\\\\]* (?: \\\\ . [^\]\\\\]* )* \] - | \\\\ . - ) (*SKIP)(*FAIL) | - \( - (?! - \? (?! <(?![!=]) | P< | \' ) - | \* - ) - ~x', - $regex - ); + return [self::NOT_FOUND]; } } - diff --git a/src/Http/RouteCollection.php b/src/Http/RouteCollection.php index 665d8c7..4e9bc0e 100644 --- a/src/Http/RouteCollection.php +++ b/src/Http/RouteCollection.php @@ -42,7 +42,7 @@ class RouteCollection public function __construct() { - $this->dataGenerator = new GroupCountBased(); + $this->dataGenerator = new DataGenerator\GroupCountBased; $this->routeParser = new RouteParser\Std; @@ -101,7 +101,8 @@ class RouteCollection $path = str_replace('//', '/', $path); $routeDatas = $this->routeParser->parse($path); foreach ($routeDatas as $routeData) { - $this->dataGenerator->addRoute($method, $routeData, $handler,$replaceHandler); + !is_null($replaceHandler) && $handler = $handler . '|' . $replaceHandler; + $this->dataGenerator->addRoute($method, $routeData, $handler); } $this->reverse[$name] = $routeDatas; -- Gitee From 32072ec7f39ad434b4a09ba13ed9fef10fd6df50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Sat, 6 Nov 2021 23:10:00 +0800 Subject: [PATCH 05/18] no message --- src/Api/ApiServiceProvider.php | 1 - src/Http/Middleware/DispatchRoute.php | 31 +++++++++++++++++++-------- src/Http/RouteCollection.php | 11 +++++++--- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/Api/ApiServiceProvider.php b/src/Api/ApiServiceProvider.php index ce23e1c..7b611a4 100644 --- a/src/Api/ApiServiceProvider.php +++ b/src/Api/ApiServiceProvider.php @@ -145,7 +145,6 @@ class ApiServiceProvider extends ServiceProvider private function setPluginRoutes(RouteCollection $route, $plugins, $pluginName) { foreach ($plugins as $plugin) { - if (empty($plugin)) exit('plugin ' . $pluginName . ' not exist.'); $prefix = '/plugin/' . $plugin['name_en'] . '/api/'; $route->group($prefix, function (RouteCollection $route) use ($plugin) { $pluginFiles = $plugin['plugin_' . $plugin['app_id']]; diff --git a/src/Http/Middleware/DispatchRoute.php b/src/Http/Middleware/DispatchRoute.php index 8952e93..7c5a018 100644 --- a/src/Http/Middleware/DispatchRoute.php +++ b/src/Http/Middleware/DispatchRoute.php @@ -61,6 +61,7 @@ class DispatchRoute implements MiddlewareInterface * @param ServerRequestInterface $request * @param RequestHandlerInterface $handler * @return ResponseInterface + * @throws \Exception */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { @@ -75,8 +76,7 @@ class DispatchRoute implements MiddlewareInterface case Dispatcher::FOUND: $handler = $routeInfo[1]; $parameters = $routeInfo[2]; - $hMap = $this->getReplaceHandlersMap(); - $handler = $hMap[$handler]??$handler; + $handler = $this->getReplaceHandlersMap($method, $handler); return $this->factory->toController($handler)($request, $parameters); } } @@ -88,19 +88,32 @@ class DispatchRoute implements MiddlewareInterface } return $this->dispatcher; } - protected function getReplaceHandlersMap(){ + + protected function getReplaceHandlersMap($method, &$handler) + { $dispatcher = $this->getDispatcher(); $staticRouteMap = $dispatcher->getStaticRouteMap(); // $variableRouteData = $dispatcher->getVariableRouteData(); - $hMap = []; - foreach ($staticRouteMap as $staticRoutes) { + foreach ($staticRouteMap as $m => $staticRoutes) { foreach ($staticRoutes as $staticRoute) { - if(strpos($staticRoute,'|')){ - $handlers = explode('|',$staticRoute); - $hMap[$handlers[1]] = $handlers[0]; + + if (is_array($staticRoute)) {//插件路由覆盖 + if ($handler == $staticRoute['replaceHandler']) { + if ($method == $staticRoute['method'] && $method == $m) { + $handler = $staticRoute['handler']; + return $handler; + } else { + throw new \Exception('handler ' . $handler . ' route method not matched'); + } + } + + } else { + if ($m == $method && $staticRoute == $handler) { + return $handler; + } } } } - return $hMap; + throw new \Exception('handler ' . $handler . ' route not found'); } } diff --git a/src/Http/RouteCollection.php b/src/Http/RouteCollection.php index 4e9bc0e..da4c5bc 100644 --- a/src/Http/RouteCollection.php +++ b/src/Http/RouteCollection.php @@ -54,9 +54,9 @@ class RouteCollection return $this->addRoute('GET', $path, $name, $handler, $replaceHandler); } - public function post($path, $name, $handler) + public function post($path, $name, $handler, $replaceHandler = null) { - return $this->addRoute('POST', $path, $name, $handler); + return $this->addRoute('POST', $path, $name, $handler, $replaceHandler); } // public function put($path, $name, $handler) @@ -101,7 +101,12 @@ class RouteCollection $path = str_replace('//', '/', $path); $routeDatas = $this->routeParser->parse($path); foreach ($routeDatas as $routeData) { - !is_null($replaceHandler) && $handler = $handler . '|' . $replaceHandler; +// !is_null($replaceHandler) && $handler = $handler . '|' . $replaceHandler; + !is_null($replaceHandler) && $handler = [ + 'method' => $method, + 'handler' => $handler, + 'replaceHandler' => $replaceHandler + ]; $this->dataGenerator->addRoute($method, $routeData, $handler); } -- Gitee From 6c461b45895a1b3faab0fc33bcebfb67390feaaf Mon Sep 17 00:00:00 2001 From: ahuchjm Date: Sun, 7 Nov 2021 12:11:51 +0800 Subject: [PATCH 06/18] no message --- src/Api/ApiServiceProvider.php | 2 +- src/Http/Middleware/DispatchRoute.php | 32 +++++++++++---------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/Api/ApiServiceProvider.php b/src/Api/ApiServiceProvider.php index 7b611a4..f41d1fd 100644 --- a/src/Api/ApiServiceProvider.php +++ b/src/Api/ApiServiceProvider.php @@ -147,7 +147,7 @@ class ApiServiceProvider extends ServiceProvider foreach ($plugins as $plugin) { $prefix = '/plugin/' . $plugin['name_en'] . '/api/'; $route->group($prefix, function (RouteCollection $route) use ($plugin) { - $pluginFiles = $plugin['plugin_' . $plugin['app_id']]; + $pluginFiles = $pltougin['plugin_' . $plugin['app_id']]; Utils::setPluginAppId($plugin['app_id']); if (isset($pluginFiles['routes'])) { foreach ($pluginFiles['routes'] as $routeFile) { diff --git a/src/Http/Middleware/DispatchRoute.php b/src/Http/Middleware/DispatchRoute.php index 7c5a018..1b9ec3c 100644 --- a/src/Http/Middleware/DispatchRoute.php +++ b/src/Http/Middleware/DispatchRoute.php @@ -89,31 +89,25 @@ class DispatchRoute implements MiddlewareInterface return $this->dispatcher; } - protected function getReplaceHandlersMap($method, &$handler) + protected function getReplaceHandlersMap($method, $handler) { $dispatcher = $this->getDispatcher(); $staticRouteMap = $dispatcher->getStaticRouteMap(); -// $variableRouteData = $dispatcher->getVariableRouteData(); + //$variableRouteData = $dispatcher->getVariableRouteData(); //不支持动态路由 + $replaceHandlers = []; foreach ($staticRouteMap as $m => $staticRoutes) { - foreach ($staticRoutes as $staticRoute) { + foreach ($staticRoutes as $urlPath => $staticRoute) { + is_array($staticRoute) && $replaceHandlers[$staticRoute['replaceHandler']] = $staticRoute; - if (is_array($staticRoute)) {//插件路由覆盖 - if ($handler == $staticRoute['replaceHandler']) { - if ($method == $staticRoute['method'] && $method == $m) { - $handler = $staticRoute['handler']; - return $handler; - } else { - throw new \Exception('handler ' . $handler . ' route method not matched'); - } - } - - } else { - if ($m == $method && $staticRoute == $handler) { - return $handler; - } - } } } - throw new \Exception('handler ' . $handler . ' route not found'); + if(isset($replaceHandlers[$handler])){ + if($replaceHandlers[$handler]['method'] == $method){ + return $replaceHandlers[$handler]['handler']; + }else{ + throw new \Exception('handler (' . $handler . ') method not matched'); + } + } + return $handler; } } -- Gitee From 0d06a1529fa7ece781fb61d447e45a72fdf93ee6 Mon Sep 17 00:00:00 2001 From: ahuchjm Date: Sun, 7 Nov 2021 12:13:46 +0800 Subject: [PATCH 07/18] no message --- src/Http/Middleware/DispatchRoute.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Middleware/DispatchRoute.php b/src/Http/Middleware/DispatchRoute.php index 1b9ec3c..a9b1e4e 100644 --- a/src/Http/Middleware/DispatchRoute.php +++ b/src/Http/Middleware/DispatchRoute.php @@ -76,7 +76,7 @@ class DispatchRoute implements MiddlewareInterface case Dispatcher::FOUND: $handler = $routeInfo[1]; $parameters = $routeInfo[2]; - $handler = $this->getReplaceHandlersMap($method, $handler); + $handler = $this->getReplaceHandler($method, $handler); return $this->factory->toController($handler)($request, $parameters); } } @@ -89,7 +89,7 @@ class DispatchRoute implements MiddlewareInterface return $this->dispatcher; } - protected function getReplaceHandlersMap($method, $handler) + protected function getReplaceHandler($method, $handler) { $dispatcher = $this->getDispatcher(); $staticRouteMap = $dispatcher->getStaticRouteMap(); -- Gitee From db243494c439af9ee5be9210cc4583c730850748 Mon Sep 17 00:00:00 2001 From: ahuchjm Date: Sun, 7 Nov 2021 12:34:47 +0800 Subject: [PATCH 08/18] no message --- src/Http/RouteCollection.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Http/RouteCollection.php b/src/Http/RouteCollection.php index da4c5bc..189c06f 100644 --- a/src/Http/RouteCollection.php +++ b/src/Http/RouteCollection.php @@ -101,7 +101,6 @@ class RouteCollection $path = str_replace('//', '/', $path); $routeDatas = $this->routeParser->parse($path); foreach ($routeDatas as $routeData) { -// !is_null($replaceHandler) && $handler = $handler . '|' . $replaceHandler; !is_null($replaceHandler) && $handler = [ 'method' => $method, 'handler' => $handler, -- Gitee From 1cec53334508a2c1d421bb8a92b62efbe3247505 Mon Sep 17 00:00:00 2001 From: ahuchjm Date: Sun, 7 Nov 2021 23:31:37 +0800 Subject: [PATCH 09/18] =?UTF-8?q?=E4=B8=B0=E5=AF=8C=E6=A1=86=E6=9E=B6?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Api/ApiServiceProvider.php | 3 ++- src/Common/Utils.php | 24 +++++++++++++++++++ .../Middleware/AuthenticateWithHeader.php | 1 + src/Http/Middleware/DispatchRoute.php | 12 ++++++---- src/Http/RouteCollection.php | 11 +++++++-- src/Http/Server.php | 6 +++-- 6 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/Api/ApiServiceProvider.php b/src/Api/ApiServiceProvider.php index f41d1fd..7b10c8f 100644 --- a/src/Api/ApiServiceProvider.php +++ b/src/Api/ApiServiceProvider.php @@ -139,6 +139,7 @@ class ApiServiceProvider extends ServiceProvider $plugins = \Discuz\Common\Utils::getPluginList(); //加载插件所有接口 $this->setPluginRoutes($route, $plugins, $pluginName); + \Discuz\Common\Utils::setRouteMap($route->getRouteData()); } @@ -147,7 +148,7 @@ class ApiServiceProvider extends ServiceProvider foreach ($plugins as $plugin) { $prefix = '/plugin/' . $plugin['name_en'] . '/api/'; $route->group($prefix, function (RouteCollection $route) use ($plugin) { - $pluginFiles = $pltougin['plugin_' . $plugin['app_id']]; + $pluginFiles = $plugin['plugin_' . $plugin['app_id']]; Utils::setPluginAppId($plugin['app_id']); if (isset($pluginFiles['routes'])) { foreach ($pluginFiles['routes'] as $routeFile) { diff --git a/src/Common/Utils.php b/src/Common/Utils.php index 32bd957..4d73156 100644 --- a/src/Common/Utils.php +++ b/src/Common/Utils.php @@ -403,4 +403,28 @@ class Utils mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) ); } + + public static function setAppKey($key, $value) + { + return app()->instance($key, $value); + } + + public static function getAppKey($key) + { + if (app()->has($key)) { + return app()->get($key); + } + return null; + } + + public static function setRouteMap($data) + { + return self::setAppKey('dzq_boot_route_data', $data); + } + + public static function getRouteMap() + { + return self::getAppKey('dzq_boot_route_data'); + } + } diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index e2800ae..6d777b5 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -66,6 +66,7 @@ class AuthenticateWithHeader implements MiddlewareInterface */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { + dd(Utils::getRouteMap()); $api = Utils::getApiName(); $this->getApiFreq($api); diff --git a/src/Http/Middleware/DispatchRoute.php b/src/Http/Middleware/DispatchRoute.php index a9b1e4e..5b7ddcf 100644 --- a/src/Http/Middleware/DispatchRoute.php +++ b/src/Http/Middleware/DispatchRoute.php @@ -74,9 +74,9 @@ class DispatchRoute implements MiddlewareInterface case Dispatcher::METHOD_NOT_ALLOWED: throw new MethodNotAllowedException($method); case Dispatcher::FOUND: - $handler = $routeInfo[1]; + $handlerInfo = $routeInfo[1]; $parameters = $routeInfo[2]; - $handler = $this->getReplaceHandler($method, $handler); + $handler = $this->getReplaceHandler($method, $handlerInfo); return $this->factory->toController($handler)($request, $parameters); } } @@ -89,7 +89,7 @@ class DispatchRoute implements MiddlewareInterface return $this->dispatcher; } - protected function getReplaceHandler($method, $handler) + protected function getReplaceHandler($method, $handlerInfo) { $dispatcher = $this->getDispatcher(); $staticRouteMap = $dispatcher->getStaticRouteMap(); @@ -97,10 +97,12 @@ class DispatchRoute implements MiddlewareInterface $replaceHandlers = []; foreach ($staticRouteMap as $m => $staticRoutes) { foreach ($staticRoutes as $urlPath => $staticRoute) { - is_array($staticRoute) && $replaceHandlers[$staticRoute['replaceHandler']] = $staticRoute; - + if(!empty($staticRoute['replaceHandler'])){ + $replaceHandlers[$staticRoute['replaceHandler']] = $staticRoute; + } } } + $handler = $handlerInfo['handler']; if(isset($replaceHandlers[$handler])){ if($replaceHandlers[$handler]['method'] == $method){ return $replaceHandlers[$handler]['handler']; diff --git a/src/Http/RouteCollection.php b/src/Http/RouteCollection.php index 189c06f..5c1d34a 100644 --- a/src/Http/RouteCollection.php +++ b/src/Http/RouteCollection.php @@ -40,6 +40,9 @@ class RouteCollection protected $currentGroupPrefix; + protected $times = 30; + protected $interval = 60; + public function __construct() { $this->dataGenerator = new DataGenerator\GroupCountBased; @@ -92,6 +95,8 @@ class RouteCollection $previousGroupPrefix = $this->currentGroupPrefix; $this->currentGroupPrefix = $previousGroupPrefix; $callback($this); + $this->times = $times; + $this->interval = $interval; $this->currentGroupPrefix = $previousGroupPrefix; } @@ -101,10 +106,12 @@ class RouteCollection $path = str_replace('//', '/', $path); $routeDatas = $this->routeParser->parse($path); foreach ($routeDatas as $routeData) { - !is_null($replaceHandler) && $handler = [ + $handler = [ 'method' => $method, 'handler' => $handler, - 'replaceHandler' => $replaceHandler + 'replaceHandler' => $replaceHandler, + 'times'=>$this->times, + 'interval'=>$this->interval ]; $this->dataGenerator->addRoute($method, $routeData, $handler); } diff --git a/src/Http/Server.php b/src/Http/Server.php index 593c547..8f162f5 100644 --- a/src/Http/Server.php +++ b/src/Http/Server.php @@ -98,10 +98,12 @@ class Server extends SiteApp $line = $error->getLine(); $type = get_class($error); $this->app->make('log')->error($error); - + $trace = $error->getTraceAsString(); return << - thrown in $file on line $line + thrown in $file on line $line
+ $message
$trace + ERROR; } -- Gitee From 0848962b280937026027c4871bc3c53cea002057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 10:25:00 +0800 Subject: [PATCH 10/18] =?UTF-8?q?=E8=B7=AF=E7=94=B1=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E9=99=90=E9=A2=91=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Middleware/AuthenticateWithHeader.php | 433 ++++++++++-------- src/Http/RouteCollection.php | 25 +- 2 files changed, 248 insertions(+), 210 deletions(-) diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index 6d777b5..27538ff 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -18,16 +18,11 @@ namespace Discuz\Http\Middleware; -use App\Common\CacheKey; use App\Common\ResponseCode; -use App\Models\Setting; use App\Models\User; use App\Passport\Repositories\AccessTokenRepository; use Discuz\Auth\Guest; -use Discuz\Base\DzqLog; -use Discuz\Cache\CacheManager; use Discuz\Common\Utils; -use Discuz\Contracts\Setting\SettingsRepository; use Illuminate\Support\Arr; use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\ResourceServer; @@ -38,256 +33,292 @@ use Psr\Http\Server\RequestHandlerInterface; class AuthenticateWithHeader implements MiddlewareInterface { - const AUTH_USER_CACHE_TTL = 300; - protected $cache; - - public function __construct(CacheManager $cache) - { - $this->cache = $cache; - } - - private $apiFreq = [ - 'get' => [ - 'freq' => 500, - 'forbidden' => 20 - ], - 'post' => [ - 'freq' => 100, - 'forbidden' => 30 - ] - ]; - - /** - * @param ServerRequestInterface $request - * @param RequestHandlerInterface $handler - * @return ResponseInterface - * @throws \League\OAuth2\Server\Exception\OAuthServerException - */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - dd(Utils::getRouteMap()); - $api = Utils::getApiName(); - $this->getApiFreq($api); - - $headerLine = $request->getHeaderLine('authorization'); - if(empty($headerLine)){ //如果header头中没有 authorization,则从cookie里面找是否有access_token - $cookies = $request->getCookieParams(); - if(!empty($cookies['access_token'])){ - $headerLine = $cookies['access_token']; - $request = $request->withHeader('authorization', $headerLine); - } - } - - // 允许 get、cookie 携带 Token - if (!$headerLine) { - $headerLine = Arr::get($request->getQueryParams(), 'token'); - - if ($headerLine) { - $request = $request->withHeader('authorization', $headerLine); - } - } - - $request = $request->withAttribute('actor', new Guest()); + list($headerLine, $request) = $this->getHeaderLine($request); if ($headerLine) { $accessTokenRepository = new AccessTokenRepository(); - $publickey = new CryptKey(storage_path('cert/public.key'), '', false); - $server = new ResourceServer($accessTokenRepository, $publickey); - try { $request = $server->validateAuthenticatedRequest($request); - } catch (\Exception $e){ - $data = [ - 'api' => $api, - 'token' => $headerLine - ]; - DzqLog::error('invalid_token', $data, $e->getMessage()); + } catch (\Exception $e) { Utils::outPut(ResponseCode::INVALID_TOKEN); } - - $this->checkLimit($api, $request); + } + if ($this->isBadRequest($request)) throw new \Exception('操作太频繁,请稍后重试'); + if ($headerLine) { // 获取Token位置,根据 Token 解析用户并查询到当前用户 $actor = $this->getActor($request); - if (!is_null($actor) && $actor->exists) { $request = $request->withoutAttribute('oauth_access_token_id')->withoutAttribute('oauth_client_id')->withoutAttribute('oauth_user_id')->withoutAttribute('oauth_scopes')->withAttribute('actor', $actor); } - } else { - $this->checkLimit($api, $request); } return $handler->handle($request); } - private function getApiFreq($api) + private function getHeaderLine($request) { - $cache = app('cache'); - $cacheKey = CacheKey::API_FREQUENCE; - if ($api == 'cache.delete') { - $cache->forget($cacheKey); + $headerLine = $request->getHeaderLine('authorization'); + if (empty($headerLine)) { //如果header头中没有 authorization,则从cookie里面找是否有access_token + $cookies = $request->getCookieParams(); + if (!empty($cookies['access_token'])) { + $headerLine = $cookies['access_token']; + $request = $request->withHeader('authorization', $headerLine); + } } - $apiFreq = $cache->get($cacheKey); - if (!empty($apiFreq)) { - $this->apiFreq = json_decode($apiFreq, true); - } else { - $apiFreqSetting = Setting::query()->where('key', 'api_freq')->first(); - if (!empty($apiFreqSetting)) { - $this->apiFreq = json_decode($apiFreqSetting['value'], true); - $cache->put($cacheKey, $apiFreqSetting['value'], 5 * 60); + // 允许 get、cookie 携带 Token + if (!$headerLine) { + $headerLine = Arr::get($request->getQueryParams(), 'token'); + + if ($headerLine) { + $request = $request->withHeader('authorization', $headerLine); } } + //初始化为游客 + $request = $request->withAttribute('actor', new Guest()); + return [$headerLine, $request]; } + private function getActor(ServerRequestInterface $request) { $userId = $request->getAttribute('oauth_user_id'); if (!$userId) { return null; } - return $this->getActorFromDatabase($userId); - - //if (app()->config('middleware_cache')) { - /*$ttl = static::AUTH_USER_CACHE_TTL; - return $this->cache->remember( - CacheKey::AUTH_USER_PREFIX.$userId, - mt_rand($ttl, $ttl + 10), - function () use ($userId) { - return $this->getActorFromDatabase($userId); - } - );*/ - /*} else { - return $this->getActorFromDatabase($userId); - }*/ - } - - private function getActorFromDatabase($userId) - { - $actor = User::find($userId); - if (!is_null($actor) && $actor->exists) { - $actor->changeUpdateAt()->save(); + $cache = app('cache'); + $key = 'dzq_login_user_by_id_' . $userId; + $actor = $cache->get($key); + if (!$actor) { + $actor = User::find($userId); + $cache->put($key, $actor, 5 * 60); } +// if (!is_null($actor) && $actor->exists) { +// $actor->changeUpdateAt()->save(); +// } return $actor; } - private function checkLimit($api, ServerRequestInterface $request) + + private function isBadRequest(ServerRequestInterface $request) { - $method = Arr::get($request->getServerParams(), 'REQUEST_METHOD', ''); + $api = $request->getUri()->getPath(); + if (Utils::startWith($api, '/backAdmin')) { + return false; + } +// $api = '/api/v3/plug/tes/hello'; + $httpMethod = Arr::get($request->getServerParams(), 'REQUEST_METHOD', ''); + $routeInfo = $this->getRouteInfo($api, $httpMethod); + $ip = ip($request->getServerParams()); $userId = $request->getAttribute('oauth_user_id'); - if (strstr($api, 'backAdmin')) { - return; + if (empty($userId)) { + $key = md5($ip . $api . $httpMethod); + } else { + $key = md5($userId . $api . $httpMethod); } - if (strtolower($method) == 'get') { - if ($this->isForbidden($api, $userId, $request, $method, $this->apiFreq['get']['freq'])) { - throw new \Exception('操作太频繁,请稍后重试'); - } + $times = $routeInfo['times']; + $interval = $routeInfo['interval']; + $delay = $routeInfo['delay'] ?: 5 * 60;//默认禁用5分钟 + $cache = app('cache'); + $count = $cache->get($key); + if (empty($count)) { + $cache->add($key, 1, $interval); + return false; } else { - if ($this->isForbidden($api, $userId, $request, $method, $this->apiFreq['post']['freq'])) { - throw new \Exception('操作太频繁,请稍后重试'); + if ($count >= $times) { + $cache->put($key, $count, $delay); + return true; + } else { + $cache->increment($key); + return false; } } } - private function isForbidden($api, $userId, ServerRequestInterface $request, $method, $max = 10, $interval = 60) + /** + * author: 流火行者 + * desc: 获取单个路由详情 + * @param $api + * @param $httpMethod + * @return bool + */ + private function getRouteInfo($api, $httpMethod) { - - $ip = ip($request->getServerParams()); - if (empty($api)) { - return true; - } - $method = strtolower($method); - - if ($this->isAttachments($api, $method) || $this->isCoskey($api, $method)) { - $maxUploadNum = app()->make(SettingsRepository::class)->get('support_max_upload_attachment_num', 'default'); - $maxLimit = $maxUploadNum ? (int)$maxUploadNum : 20; - } - - if (empty($userId)) { - $key = 'api_limit_by_ip_' . md5($ip . $api . $method); - } else { - $key = 'api_limit_by_uid_' . md5($userId . '_' . $api . $method); + $routeMaps = Utils::getRouteMap(); + $staticMaps = $routeMaps[0] ?? []; + $variableMaps = $routeMaps[1] ?? []; + foreach ($staticMaps as $method => $staticMap) { + if ($method == $httpMethod && isset($staticMap[$api])) return $staticMap[$api]; } - if ($this->isRegister($api, $method)) { - return $this->setLimit($key, $method, 10, 10 * 60); + foreach ($variableMaps as $method => $variableMap) { + $route = $this->dispatchVariableRoute($variableMap, $api); + if ($method == $httpMethod && $route) return $route; } - if ($this->isAttachments($api, $method)) { - return $this->setLimit($key, $method, $maxLimit, 5 * 60); - } - if ($this->isPoll($api)) { - return $this->setLimit($key, $method, 200, 60); - } - - if ($this->isCoskey($api, $method)) { - return $this->setLimit($key, $method, $maxLimit, 30); - } - if ($this->isPayOrder($api, $method)) { - return $this->setLimit($key, $method, 3, 10); - } - return $this->setLimit($key, $method, $max); + return false; } - private function isRegister($api, $method) - { - return $api == 'users/username.register' && $method == 'post'; - } - - private function isAttachments($api, $method) - { - return $api == 'attachments' && $method == 'post'; - } - - private function isPoll($api) - { - $pollapi = [ - 'users/pc/wechat/h5.login', - 'users/pc/wechat/h5.bind', - 'users/pc/wechat/miniprogram.bind', - 'users/pc/wechat/miniprogram.login', - 'users/pc/wechat.rebind.poll', - 'dialog/message', - 'unreadnotification', - 'dialog.update' - ]; - return in_array($api, $pollapi); - } - - private function isCoskey($api, $method) + /** + * author: 流火行者 + * desc: 解析可变路由详情 + * @param $routeData + * @param $uri + * @return bool + */ + private function dispatchVariableRoute($routeData, $uri) { - return $api == 'coskey' && $method == 'post'; - } - - private function isPayOrder($api, $method){ - return $api == 'trade/pay/order' && $method == 'post'; + foreach ($routeData as $data) { + if (!preg_match($data['regex'], $uri, $matches)) { + continue; + } + list($handler, $varNames) = $data['routeMap'][count($matches)]; + $vars = []; + $i = 0; + foreach ($varNames as $varName) { + $vars[$varName] = $matches[++$i]; + } + return $handler; + } + return false; } +// private function getApiFreq($api) +// { +// $cache = app('cache'); +// $cacheKey = CacheKey::API_FREQUENCE; +// if ($api == 'cache.delete') { +// $cache->forget($cacheKey); +// } +// $apiFreq = $cache->get($cacheKey); +// if (!empty($apiFreq)) { +// $this->apiFreq = json_decode($apiFreq, true); +// } else { +// $apiFreqSetting = Setting::query()->where('key', 'api_freq')->first(); +// if (!empty($apiFreqSetting)) { +// $this->apiFreq = json_decode($apiFreqSetting['value'], true); +// $cache->put($cacheKey, $apiFreqSetting['value'], 5 * 60); +// } +// } +// } +// private function checkLimit($api, ServerRequestInterface $request) +// { +// $method = Arr::get($request->getServerParams(), 'REQUEST_METHOD', ''); +// $userId = $request->getAttribute('oauth_user_id'); +// if (strstr($api, 'backAdmin')) { +// return; +// } +// if (strtolower($method) == 'get') { +// if ($this->isForbidden($api, $userId, $request, $method, $this->apiFreq['get']['freq'])) { +// throw new \Exception('操作太频繁,请稍后重试'); +// } +// } else { +// if ($this->isForbidden($api, $userId, $request, $method, $this->apiFreq['post']['freq'])) { +// throw new \Exception('操作太频繁,请稍后重试'); +// } +// } +// } +// +// private function isForbidden($api, $userId, ServerRequestInterface $request, $method, $max = 10, $interval = 60) +// { +// +// $ip = ip($request->getServerParams()); +// if (empty($api)) { +// return true; +// } +// $method = strtolower($method); +// +// if ($this->isAttachments($api, $method) || $this->isCoskey($api, $method)) { +// $maxUploadNum = app()->make(SettingsRepository::class)->get('support_max_upload_attachment_num', 'default'); +// $maxLimit = $maxUploadNum ? (int)$maxUploadNum : 20; +// } +// +// if (empty($userId)) { +// $key = 'api_limit_by_ip_' . md5($ip . $api . $method); +// } else { +// $key = 'api_limit_by_uid_' . md5($userId . '_' . $api . $method); +// } +// if ($this->isRegister($api, $method)) { +// return $this->setLimit($key, $method, 10, 10 * 60); +// } +// if ($this->isAttachments($api, $method)) { +// return $this->setLimit($key, $method, $maxLimit, 5 * 60); +// } +// if ($this->isPoll($api)) { +// return $this->setLimit($key, $method, 200, 60); +// } +// +// if ($this->isCoskey($api, $method)) { +// return $this->setLimit($key, $method, $maxLimit, 30); +// } +// if ($this->isPayOrder($api, $method)) { +// return $this->setLimit($key, $method, 3, 10); +// } +// return $this->setLimit($key, $method, $max); +// } + +// private function isRegister($api, $method) +// { +// return $api == 'users/username.register' && $method == 'post'; +// } +// +// private function isAttachments($api, $method) +// { +// return $api == 'attachments' && $method == 'post'; +// } +// +// private function isPoll($api) +// { +// $pollapi = [ +// 'users/pc/wechat/h5.login', +// 'users/pc/wechat/h5.bind', +// 'users/pc/wechat/miniprogram.bind', +// 'users/pc/wechat/miniprogram.login', +// 'users/pc/wechat.rebind.poll', +// 'dialog/message', +// 'unreadnotification', +// 'dialog.update' +// ]; +// return in_array($api, $pollapi); +// } +// +// private function isCoskey($api, $method) +// { +// return $api == 'coskey' && $method == 'post'; +// } +// +// private function isPayOrder($api, $method) +// { +// return $api == 'trade/pay/order' && $method == 'post'; +// } /* * $max interage 每分钟最大调用次数 * $defaultDelay Boolen 超过调用次数禁止秒数 */ - private function setLimit($key, $method, $max, $defaultDelay = null) - { - $cache = app('cache'); - $count = $cache->get($key); - - if (empty($count)) { - $cache->add($key, 1, 60); - return false; - } else { - if ($count >= $max) { - if ($defaultDelay == null) { - if ($method == 'get') { - $cache->put($key, $count, $this->apiFreq['get']['forbidden']); - } else { - $cache->put($key, $count, $this->apiFreq['post']['forbidden']); - } - } else { - $cache->put($key, $count, $defaultDelay); - } - return true; - } else { - $cache->increment($key); - return false; - } - } - } +// private function setLimit($key, $method, $max, $defaultDelay = null) +// { +// $cache = app('cache'); +// $count = $cache->get($key); +// +// if (empty($count)) { +// $cache->add($key, 1, 60); +// return false; +// } else { +// if ($count >= $max) { +// if ($defaultDelay == null) { +// if ($method == 'get') { +// $cache->put($key, $count, $this->apiFreq['get']['forbidden']); +// } else { +// $cache->put($key, $count, $this->apiFreq['post']['forbidden']); +// } +// } else { +// $cache->put($key, $count, $defaultDelay); +// } +// return true; +// } else { +// $cache->increment($key); +// return false; +// } +// } +// } } diff --git a/src/Http/RouteCollection.php b/src/Http/RouteCollection.php index 5c1d34a..c4ebfbe 100644 --- a/src/Http/RouteCollection.php +++ b/src/Http/RouteCollection.php @@ -40,8 +40,9 @@ class RouteCollection protected $currentGroupPrefix; - protected $times = 30; - protected $interval = 60; + protected $times; + protected $interval; + protected $delay; public function __construct() { @@ -50,6 +51,9 @@ class RouteCollection $this->routeParser = new RouteParser\Std; $this->currentGroupPrefix = ''; + $this->times = null; + $this->interval = null; + $this->delay = null; } public function get($path, $name, $handler, $replaceHandler = null) @@ -89,15 +93,17 @@ class RouteCollection * @param callable $callback * @param int $times 访问次数 * @param int $interval 时间间隔(秒) + * @param int $delay 超过限频禁用时长(秒) */ - public function withFrequency(callable $callback, $times = 100, $interval = 60) + public function withFrequency(callable $callback, $times = 100, $interval = 60, $delay = 300) { - $previousGroupPrefix = $this->currentGroupPrefix; - $this->currentGroupPrefix = $previousGroupPrefix; - $callback($this); $this->times = $times; $this->interval = $interval; - $this->currentGroupPrefix = $previousGroupPrefix; + $this->delay = $delay; + $callback($this); + $this->times = null; + $this->interval = null; + $this->delay = null; } public function addRoute($method, $path, $name, $handler, $replaceHandler = null) @@ -110,8 +116,9 @@ class RouteCollection 'method' => $method, 'handler' => $handler, 'replaceHandler' => $replaceHandler, - 'times'=>$this->times, - 'interval'=>$this->interval + 'times' => $this->times, + 'interval' => $this->interval, + 'delay' => $this->delay ]; $this->dataGenerator->addRoute($method, $routeData, $handler); } -- Gitee From 05266b34c383aef1c56c3587fe560c3797a3a356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 10:52:06 +0800 Subject: [PATCH 11/18] no message --- src/Http/Middleware/AuthenticateWithHeader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index 27538ff..02c2e41 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -93,7 +93,7 @@ class AuthenticateWithHeader implements MiddlewareInterface $actor = $cache->get($key); if (!$actor) { $actor = User::find($userId); - $cache->put($key, $actor, 5 * 60); + $cache->put($key, $actor, 3 * 60); } // if (!is_null($actor) && $actor->exists) { // $actor->changeUpdateAt()->save(); -- Gitee From 2dfdcd6ed1920ede9eb65d66bc06daaa4296ca98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 12:06:58 +0800 Subject: [PATCH 12/18] no message --- src/Http/Middleware/AuthenticateWithHeader.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index 02c2e41..607b32e 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -118,9 +118,9 @@ class AuthenticateWithHeader implements MiddlewareInterface } else { $key = md5($userId . $api . $httpMethod); } - $times = $routeInfo['times']; - $interval = $routeInfo['interval']; - $delay = $routeInfo['delay'] ?: 5 * 60;//默认禁用5分钟 + $times = $routeInfo['times'] ?: 100; + $interval = $routeInfo['interval'] ?: 60; + $delay = $routeInfo['delay'] ?: 300;//默认禁用5分钟 $cache = app('cache'); $count = $cache->get($key); if (empty($count)) { -- Gitee From e35fb69d6578ae633c650ec2bdc62fd7261f904d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 12:09:14 +0800 Subject: [PATCH 13/18] no message --- src/Http/Middleware/AuthenticateWithHeader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index 607b32e..84b842f 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -118,7 +118,7 @@ class AuthenticateWithHeader implements MiddlewareInterface } else { $key = md5($userId . $api . $httpMethod); } - $times = $routeInfo['times'] ?: 100; + $times = $routeInfo['times'] ?: 50; $interval = $routeInfo['interval'] ?: 60; $delay = $routeInfo['delay'] ?: 300;//默认禁用5分钟 $cache = app('cache'); -- Gitee From e0bbf305d2c655de2844def762a870c1fa6b8a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 12:10:56 +0800 Subject: [PATCH 14/18] no message --- src/Http/Middleware/AuthenticateWithHeader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index 84b842f..298293c 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -118,8 +118,8 @@ class AuthenticateWithHeader implements MiddlewareInterface } else { $key = md5($userId . $api . $httpMethod); } - $times = $routeInfo['times'] ?: 50; - $interval = $routeInfo['interval'] ?: 60; + $times = $routeInfo['times'] ?: 20; + $interval = $routeInfo['interval'] ?: 30; $delay = $routeInfo['delay'] ?: 300;//默认禁用5分钟 $cache = app('cache'); $count = $cache->get($key); -- Gitee From 9a04e4a34eb9cebb82a0171aa05b34d565d59656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 12:11:12 +0800 Subject: [PATCH 15/18] no message --- src/Http/Middleware/AuthenticateWithHeader.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index 298293c..25ac864 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -108,7 +108,6 @@ class AuthenticateWithHeader implements MiddlewareInterface if (Utils::startWith($api, '/backAdmin')) { return false; } -// $api = '/api/v3/plug/tes/hello'; $httpMethod = Arr::get($request->getServerParams(), 'REQUEST_METHOD', ''); $routeInfo = $this->getRouteInfo($api, $httpMethod); $ip = ip($request->getServerParams()); -- Gitee From 0b227fda87d1d82d27a3b483757ec643977ab3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 13:05:55 +0800 Subject: [PATCH 16/18] no message --- src/Http/Middleware/AuthenticateWithHeader.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index 25ac864..7d765f5 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -117,8 +117,13 @@ class AuthenticateWithHeader implements MiddlewareInterface } else { $key = md5($userId . $api . $httpMethod); } - $times = $routeInfo['times'] ?: 20; - $interval = $routeInfo['interval'] ?: 30; + if($httpMethod == 'GET'){ + $times = $routeInfo['times'] ?: 20; + $interval = $routeInfo['interval'] ?: 30; + }else{ + $times = $routeInfo['times'] ?: 30; + $interval = $routeInfo['interval'] ?: 60; + } $delay = $routeInfo['delay'] ?: 300;//默认禁用5分钟 $cache = app('cache'); $count = $cache->get($key); -- Gitee From e1be4772eb43772acbb5cc10bf6ea57812a6da7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 15:10:30 +0800 Subject: [PATCH 17/18] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Api/ApiServiceProvider.php | 21 +-------------------- src/Common/Utils.php | 22 ++++++++++++++++++++++ src/Web/WebServiceProvider.php | 3 +++ 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/Api/ApiServiceProvider.php b/src/Api/ApiServiceProvider.php index 7b10c8f..e3c2c8a 100644 --- a/src/Api/ApiServiceProvider.php +++ b/src/Api/ApiServiceProvider.php @@ -136,29 +136,10 @@ class ApiServiceProvider extends ServiceProvider require $this->app->basePath('routes/api.php'); }); } - $plugins = \Discuz\Common\Utils::getPluginList(); - //加载插件所有接口 - $this->setPluginRoutes($route, $plugins, $pluginName); + \Discuz\Common\Utils::includePluginRoutes($route); \Discuz\Common\Utils::setRouteMap($route->getRouteData()); } - - private function setPluginRoutes(RouteCollection $route, $plugins, $pluginName) - { - foreach ($plugins as $plugin) { - $prefix = '/plugin/' . $plugin['name_en'] . '/api/'; - $route->group($prefix, function (RouteCollection $route) use ($plugin) { - $pluginFiles = $plugin['plugin_' . $plugin['app_id']]; - Utils::setPluginAppId($plugin['app_id']); - if (isset($pluginFiles['routes'])) { - foreach ($pluginFiles['routes'] as $routeFile) { - require_once $routeFile; - } - } - }); - } - } - private function matchPrefix($uri, $prefix) { $p = '/' . $prefix;//兼容前端错误的url拼接 diff --git a/src/Common/Utils.php b/src/Common/Utils.php index af18c10..4d2c461 100644 --- a/src/Common/Utils.php +++ b/src/Common/Utils.php @@ -7,6 +7,7 @@ use App\Common\DzqConst; use App\Common\ResponseCode; use Discuz\Base\DzqCache; use Discuz\Base\DzqLog; +use Discuz\Http\RouteCollection; use Illuminate\Http\Request; use Illuminate\Support\Str; use Discuz\Http\DiscuzResponseFactory; @@ -249,6 +250,27 @@ class Utils return $plugins; } + /** + * @desc 一次性加载所有插件的路由文件 + * @param RouteCollection $route + * @return RouteCollection + */ + public static function includePluginRoutes(RouteCollection &$route){ + $plugins = self::getPluginList(); + foreach ($plugins as $plugin) { + $prefix = '/plugin/' . $plugin['name_en'] . '/api/'; + $route->group($prefix, function (RouteCollection $route) use ($plugin) { + $pluginFiles = $plugin['plugin_' . $plugin['app_id']]; + \App\Common\Utils::setPluginAppId($plugin['app_id']); + if (isset($pluginFiles['routes'])) { + foreach ($pluginFiles['routes'] as $routeFile) { + require_once $routeFile; + } + } + }); + } + return $route; + } public static function runConsoleCmd($cmd, $params) { $reader = function & ($object, $property) { diff --git a/src/Web/WebServiceProvider.php b/src/Web/WebServiceProvider.php index cbf89a8..1cb3a07 100644 --- a/src/Web/WebServiceProvider.php +++ b/src/Web/WebServiceProvider.php @@ -18,6 +18,7 @@ namespace Discuz\Web; +use App\Common\Utils; use Discuz\Http\Middleware\DispatchRoute; use Discuz\Http\Middleware\HandleErrorsWithView; use Discuz\Http\Middleware\HandleErrorsWithWhoops; @@ -57,5 +58,7 @@ class WebServiceProvider extends ServiceProvider $route->group('', function (RouteCollection $route) { require $this->app->basePath('routes/web.php'); }); + \Discuz\Common\Utils::includePluginRoutes($route); + \Discuz\Common\Utils::setRouteMap($route->getRouteData()); } } -- Gitee From 90005973c7bfc5458457a8f7e6d29d0c0b0bf357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=81=E7=81=AB=E8=A1=8C=E8=80=85?= Date: Tue, 9 Nov 2021 15:15:24 +0800 Subject: [PATCH 18/18] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Middleware/AuthenticateWithHeader.php | 139 ------------------ 1 file changed, 139 deletions(-) diff --git a/src/Http/Middleware/AuthenticateWithHeader.php b/src/Http/Middleware/AuthenticateWithHeader.php index 7d765f5..1fe2570 100644 --- a/src/Http/Middleware/AuthenticateWithHeader.php +++ b/src/Http/Middleware/AuthenticateWithHeader.php @@ -186,143 +186,4 @@ class AuthenticateWithHeader implements MiddlewareInterface } return false; } -// private function getApiFreq($api) -// { -// $cache = app('cache'); -// $cacheKey = CacheKey::API_FREQUENCE; -// if ($api == 'cache.delete') { -// $cache->forget($cacheKey); -// } -// $apiFreq = $cache->get($cacheKey); -// if (!empty($apiFreq)) { -// $this->apiFreq = json_decode($apiFreq, true); -// } else { -// $apiFreqSetting = Setting::query()->where('key', 'api_freq')->first(); -// if (!empty($apiFreqSetting)) { -// $this->apiFreq = json_decode($apiFreqSetting['value'], true); -// $cache->put($cacheKey, $apiFreqSetting['value'], 5 * 60); -// } -// } -// } -// private function checkLimit($api, ServerRequestInterface $request) -// { -// $method = Arr::get($request->getServerParams(), 'REQUEST_METHOD', ''); -// $userId = $request->getAttribute('oauth_user_id'); -// if (strstr($api, 'backAdmin')) { -// return; -// } -// if (strtolower($method) == 'get') { -// if ($this->isForbidden($api, $userId, $request, $method, $this->apiFreq['get']['freq'])) { -// throw new \Exception('操作太频繁,请稍后重试'); -// } -// } else { -// if ($this->isForbidden($api, $userId, $request, $method, $this->apiFreq['post']['freq'])) { -// throw new \Exception('操作太频繁,请稍后重试'); -// } -// } -// } -// -// private function isForbidden($api, $userId, ServerRequestInterface $request, $method, $max = 10, $interval = 60) -// { -// -// $ip = ip($request->getServerParams()); -// if (empty($api)) { -// return true; -// } -// $method = strtolower($method); -// -// if ($this->isAttachments($api, $method) || $this->isCoskey($api, $method)) { -// $maxUploadNum = app()->make(SettingsRepository::class)->get('support_max_upload_attachment_num', 'default'); -// $maxLimit = $maxUploadNum ? (int)$maxUploadNum : 20; -// } -// -// if (empty($userId)) { -// $key = 'api_limit_by_ip_' . md5($ip . $api . $method); -// } else { -// $key = 'api_limit_by_uid_' . md5($userId . '_' . $api . $method); -// } -// if ($this->isRegister($api, $method)) { -// return $this->setLimit($key, $method, 10, 10 * 60); -// } -// if ($this->isAttachments($api, $method)) { -// return $this->setLimit($key, $method, $maxLimit, 5 * 60); -// } -// if ($this->isPoll($api)) { -// return $this->setLimit($key, $method, 200, 60); -// } -// -// if ($this->isCoskey($api, $method)) { -// return $this->setLimit($key, $method, $maxLimit, 30); -// } -// if ($this->isPayOrder($api, $method)) { -// return $this->setLimit($key, $method, 3, 10); -// } -// return $this->setLimit($key, $method, $max); -// } - -// private function isRegister($api, $method) -// { -// return $api == 'users/username.register' && $method == 'post'; -// } -// -// private function isAttachments($api, $method) -// { -// return $api == 'attachments' && $method == 'post'; -// } -// -// private function isPoll($api) -// { -// $pollapi = [ -// 'users/pc/wechat/h5.login', -// 'users/pc/wechat/h5.bind', -// 'users/pc/wechat/miniprogram.bind', -// 'users/pc/wechat/miniprogram.login', -// 'users/pc/wechat.rebind.poll', -// 'dialog/message', -// 'unreadnotification', -// 'dialog.update' -// ]; -// return in_array($api, $pollapi); -// } -// -// private function isCoskey($api, $method) -// { -// return $api == 'coskey' && $method == 'post'; -// } -// -// private function isPayOrder($api, $method) -// { -// return $api == 'trade/pay/order' && $method == 'post'; -// } - - /* - * $max interage 每分钟最大调用次数 - * $defaultDelay Boolen 超过调用次数禁止秒数 - */ -// private function setLimit($key, $method, $max, $defaultDelay = null) -// { -// $cache = app('cache'); -// $count = $cache->get($key); -// -// if (empty($count)) { -// $cache->add($key, 1, 60); -// return false; -// } else { -// if ($count >= $max) { -// if ($defaultDelay == null) { -// if ($method == 'get') { -// $cache->put($key, $count, $this->apiFreq['get']['forbidden']); -// } else { -// $cache->put($key, $count, $this->apiFreq['post']['forbidden']); -// } -// } else { -// $cache->put($key, $count, $defaultDelay); -// } -// return true; -// } else { -// $cache->increment($key); -// return false; -// } -// } -// } } -- Gitee