diff --git a/lib/private/Route/CachingRouter.php b/lib/private/Route/CachingRouter.php index 7dd26827d3c..9ceb08b61e2 100644 --- a/lib/private/Route/CachingRouter.php +++ b/lib/private/Route/CachingRouter.php @@ -15,6 +15,7 @@ use OCP\IConfig; use OCP\IRequest; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; +use Symfony\Component\Routing\RouteCollection; class CachingRouter extends Router { protected ICache $cache; @@ -54,4 +55,62 @@ class CachingRouter extends Router { return $url; } } + + private function serializeRouteCollection(RouteCollection $collection): array { + return array_map( + fn (Route $route) => [$route->getPath(), $route->getDefaults(), $route->getRequirements(), $route->getOptions(), $route->getHost(), $route->getSchemes(), $route->getMethods(), $route->getCondition()], + $collection->all(), + ); + } + + private function unserializeRouteCollection(array $data): RouteCollection { + $collection = new RouteCollection(); + foreach ($data as $name => $details) { + $route = new Route(...$details); + $collection->add($name, $route); + } + return $collection; + } + + /** + * Loads the routes + * + * @param null|string $app + */ + public function loadRoutes($app = null): void { + $this->eventLogger->start('cacheroute:load:' . $app, 'Loading Routes (using cache) for ' . $app); + if (is_string($app)) { + $app = $this->appManager->cleanAppId($app); + } + + $requestedApp = $app; + if ($this->loaded) { + $this->eventLogger->end('cacheroute:load:' . $app); + return; + } + if (is_null($app)) { + $cachedRoutes = $this->cache->get('root:'); + if ($cachedRoutes) { + $this->root = $this->unserializeRouteCollection($cachedRoutes); + $this->loaded = true; + $this->eventLogger->end('cacheroute:load:' . $app); + return; + } + } else { + if (isset($this->loadedApps[$app])) { + $this->eventLogger->end('cacheroute:load:' . $app); + return; + } + $cachedRoutes = $this->cache->get('root:' . $requestedApp); + if ($cachedRoutes) { + $this->root = $this->unserializeRouteCollection($cachedRoutes); + $this->loadedApps[$app] = true; + $this->eventLogger->end('cacheroute:load:' . $app); + return; + } + } + parent::loadRoutes($app); + $this->cache->set('root:' . $requestedApp, $this->serializeRouteCollection($this->root), 3600); + $this->eventLogger->end('cacheroute:load:' . $app); + } }