initAnnotationRoute(AnnotationCollector::list()); $this->initConfigRoute(); } public function getDispatcher(string $serverName): Dispatcher { if (isset($this->dispatchers[$serverName])) { return $this->dispatchers[$serverName]; } $router = $this->getRouter($serverName); return $this->dispatchers[$serverName] = new GroupCountBased($router->getData()); } public function initConfigRoute() { Router::init($this); foreach ($this->routes as $route) { if (file_exists($route)) { require_once $route; } } } public function getRouter(string $serverName): RouteCollector { if (isset($this->routers[$serverName])) { return $this->routers[$serverName]; } $parser = new Std(); $generator = new DataGenerator(); return $this->routers[$serverName] = new RouteCollector($parser, $generator); } private function initAnnotationRoute(array $collector): void { foreach ($collector as $className => $metadata) { if (isset($metadata['_c'][RpcService::class])) { $middlewares = $this->handleMiddleware($metadata['_c']); $this->handleRpcService($className, $metadata['_c'][RpcService::class], $metadata['_m'] ?? [], $middlewares); } } } /** * Register route according to RpcService annotation. */ private function handleRpcService( string $className, RpcService $annotation, array $methodMetadata, array $middlewares = [] ): void { $prefix = $annotation->name ?: $className; $router = $this->getRouter($annotation->server); $publicMethods = ReflectionManager::reflectClass($className)->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($publicMethods as $reflectionMethod) { $methodName = $reflectionMethod->getName(); if (Str::startsWith($methodName, '__')) { continue; } $path = $this->pathGenerator->generate($prefix, $methodName); $router->addRoute($path, [ $className, $methodName, ]); $methodMiddlewares = $middlewares; // Handle method level middlewares. if (isset($methodMetadata[$methodName])) { $methodMiddlewares = array_merge($this->handleMiddleware($methodMetadata[$methodName]), $middlewares); } // TODO: Remove array_unique from v3.0. $methodMiddlewares = array_unique($methodMiddlewares); // Register middlewares. MiddlewareManager::addMiddlewares($annotation->server, $path, 'POST', $methodMiddlewares); // Trigger the AfterPathRegister event. $this->eventDispatcher->dispatch(new AfterPathRegister($path, $className, $methodName, $annotation)); } } private function handleMiddleware(array $metadata): array { $hasMiddlewares = isset($metadata[Middlewares::class]); $hasMiddleware = isset($metadata[Middleware::class]); if (! $hasMiddlewares && ! $hasMiddleware) { return []; } if ($hasMiddlewares && $hasMiddleware) { throw new ConflictAnnotationException('Could not use @Middlewares and @Middleware annotation at the same times at same level.'); } if ($hasMiddlewares) { // @Middlewares /** @var Middlewares $middlewares */ $middlewares = $metadata[Middlewares::class]; $result = []; foreach ($middlewares->middlewares as $middleware) { $result[] = $middleware->middleware; } return $result; } // @Middleware /** @var Middleware $middleware */ $middleware = $metadata[Middleware::class]; return [$middleware->middleware]; } }