X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FApp%2FRouter.php;h=6e390a84d9b145f4fcf76a86b1b30ff22001dc9c;hb=204e52ea307b182175ae0c64d6eb69c71a104658;hp=70e31687eeeae13a45354d77936e684737b51f18;hpb=e56a53647bd5469551bf4f9ef2df50a5dd16b943;p=friendica.git diff --git a/src/App/Router.php b/src/App/Router.php index 70e31687ee..6e390a84d9 100644 --- a/src/App/Router.php +++ b/src/App/Router.php @@ -37,10 +37,12 @@ use Friendica\Core\Lock\Capability\ICanLock; use Friendica\LegacyModule; use Friendica\Module\HTTPException\MethodNotAllowed; use Friendica\Module\HTTPException\PageNotFound; +use Friendica\Module\Special\Options; use Friendica\Network\HTTPException; use Friendica\Network\HTTPException\MethodNotAllowedException; -use Friendica\Network\HTTPException\NoContentException; use Friendica\Network\HTTPException\NotFoundException; +use Friendica\Util\Router\FriendicaGroupCountBased; +use Psr\Log\LoggerInterface; /** * Wrapper for FastRoute\Router @@ -73,11 +75,6 @@ class Router /** @var RouteCollector */ protected $routeCollector; - /** - * @var string The HTTP method - */ - private $httpMethod; - /** * @var array Module parameters */ @@ -98,6 +95,12 @@ class Router /** @var IManageConfigValues */ private $config; + /** @var LoggerInterface */ + private $logger; + + /** @var float */ + private $dice_profiler_threshold; + /** @var Dice */ private $dice; @@ -115,34 +118,24 @@ class Router * @param ICanLock $lock * @param IManageConfigValues $config * @param Arguments $args + * @param LoggerInterface $logger * @param Dice $dice * @param RouteCollector|null $routeCollector */ - public function __construct(array $server, string $baseRoutesFilepath, L10n $l10n, ICanCache $cache, ICanLock $lock, IManageConfigValues $config, Arguments $args, Dice $dice, RouteCollector $routeCollector = null) + public function __construct(array $server, string $baseRoutesFilepath, L10n $l10n, ICanCache $cache, ICanLock $lock, IManageConfigValues $config, Arguments $args, LoggerInterface $logger, Dice $dice, RouteCollector $routeCollector = null) { - $this->baseRoutesFilepath = $baseRoutesFilepath; - $this->l10n = $l10n; - $this->cache = $cache; - $this->lock = $lock; - $this->args = $args; - $this->config = $config; - $this->dice = $dice; - $this->server = $server; - - $httpMethod = $this->server['REQUEST_METHOD'] ?? self::GET; - - // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS - // @todo Check allowed methods per requested path - if ($httpMethod === static::OPTIONS) { - header('Allow: ' . implode(',', Router::ALLOWED_METHODS)); - throw new NoContentException(); - } - - $this->httpMethod = in_array($httpMethod, self::ALLOWED_METHODS) ? $httpMethod : self::GET; - - $this->routeCollector = isset($routeCollector) ? - $routeCollector : - new RouteCollector(new Std(), new GroupCountBased()); + $this->baseRoutesFilepath = $baseRoutesFilepath; + $this->l10n = $l10n; + $this->cache = $cache; + $this->lock = $lock; + $this->args = $args; + $this->config = $config; + $this->dice = $dice; + $this->server = $server; + $this->logger = $logger; + $this->dice_profiler_threshold = $config->get('system', 'dice_profiler_threshold', 0); + + $this->routeCollector = $routeCollector ?? new RouteCollector(new Std(), new GroupCountBased()); if ($this->baseRoutesFilepath && !file_exists($this->baseRoutesFilepath)) { throw new HTTPException\InternalServerErrorException('Routes file path does\'n exist.'); @@ -161,9 +154,7 @@ class Router */ public function loadRoutes(array $routes) { - $routeCollector = (isset($this->routeCollector) ? - $this->routeCollector : - new RouteCollector(new Std(), new GroupCountBased())); + $routeCollector = ($this->routeCollector ?? new RouteCollector(new Std(), new GroupCountBased())); $this->addRoutes($routeCollector, $routes); @@ -181,7 +172,10 @@ class Router if ($this->isGroup($config)) { $this->addGroup($route, $config, $routeCollector); } elseif ($this->isRoute($config)) { - $routeCollector->addRoute($config[1], $route, $config[0]); + // Always add the OPTIONS endpoint to a route + $httpMethods = (array) $config[1]; + $httpMethods[] = Router::OPTIONS; + $routeCollector->addRoute($httpMethods, $route, $config[0]); } else { throw new HTTPException\InternalServerErrorException("Wrong route config for route '" . print_r($route, true) . "'"); } @@ -264,18 +258,24 @@ class Router $cmd = $this->args->getCommand(); $cmd = '/' . ltrim($cmd, '/'); - $dispatcher = new Dispatcher\GroupCountBased($this->getCachedDispatchData()); + $dispatcher = new FriendicaGroupCountBased($this->getCachedDispatchData()); $this->parameters = []; - $routeInfo = $dispatcher->dispatch($this->httpMethod, $cmd); - if ($routeInfo[0] === Dispatcher::FOUND) { - $moduleClass = $routeInfo[1]; - $this->parameters = $routeInfo[2]; - } elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) { - throw new HTTPException\MethodNotAllowedException($this->l10n->t('Method not allowed for this module. Allowed method(s): %s', implode(', ', $routeInfo[1]))); + // Check if the HTTP method is OPTIONS and return the special Options Module with the possible HTTP methods + if ($this->args->getMethod() === static::OPTIONS) { + $moduleClass = Options::class; + $this->parameters = ['allowedMethods' => $dispatcher->getOptions($cmd)]; } else { - throw new HTTPException\NotFoundException($this->l10n->t('Page not found.')); + $routeInfo = $dispatcher->dispatch($this->args->getMethod(), $cmd); + if ($routeInfo[0] === Dispatcher::FOUND) { + $moduleClass = $routeInfo[1]; + $this->parameters = $routeInfo[2]; + } elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) { + throw new HTTPException\MethodNotAllowedException($this->l10n->t('Method not allowed for this module. Allowed method(s): %s', implode(', ', $routeInfo[1]))); + } else { + throw new HTTPException\NotFoundException($this->l10n->t('Page not found.')); + } } return $moduleClass; @@ -323,8 +323,19 @@ class Router $module_class = $module_class ?: PageNotFound::class; } - /** @var ICanHandleRequests $module */ - return $this->dice->create($module_class, $module_parameters); + $stamp = microtime(true); + + try { + /** @var ICanHandleRequests $module */ + return $this->dice->create($module_class, $module_parameters); + } finally { + if ($this->dice_profiler_threshold > 0) { + $dur = floatval(microtime(true) - $stamp); + if ($dur >= $this->dice_profiler_threshold) { + $this->logger->warning('Dice module creation lasts too long.', ['duration' => round($dur, 3), 'module' => $module_class, 'parameters' => $module_parameters]); + } + } + } } /** @@ -364,13 +375,13 @@ class Router */ private function getCachedDispatchData() { - $routerDispatchData = $this->cache->get('routerDispatchData'); + $routerDispatchData = $this->cache->get('routerDispatchData'); $lastRoutesFileModifiedTime = $this->cache->get('lastRoutesFileModifiedTime'); - $forceRecompute = false; + $forceRecompute = false; if ($this->baseRoutesFilepath) { $routesFileModifiedTime = filemtime($this->baseRoutesFilepath); - $forceRecompute = $lastRoutesFileModifiedTime != $routesFileModifiedTime; + $forceRecompute = $lastRoutesFileModifiedTime != $routesFileModifiedTime; } if (!$forceRecompute && $routerDispatchData) {