use Friendica\Core;
use Friendica\LegacyModule;
use Friendica\Module\Home;
-use Friendica\Module\PageNotFound;
+use Friendica\Module\HTTPException\MethodNotAllowed;
+use Friendica\Module\HTTPException\PageNotFound;
+use Friendica\Network\HTTPException\MethodNotAllowedException;
+use Friendica\Network\HTTPException\NotFoundException;
use Psr\Log\LoggerInterface;
/**
{
$printNotAllowedAddon = false;
+ $module_class = null;
/**
* ROUTING
*
* From the request URL, routing consists of obtaining the name of a BaseModule-extending class of which the
* post() and/or content() static methods can be respectively called to produce a data change or an output.
**/
- $module_class = $router->getModuleClass($args->getCommand());
-
- // Then we try addon-provided modules that we wrap in the LegacyModule class
- if (!$module_class && Core\Addon::isEnabled($this->module) && file_exists("addon/{$this->module}/{$this->module}.php")) {
- //Check if module is an app and if public access to apps is allowed or not
- $privateapps = $config->get('config', 'private_addons', false);
- if ((!local_user()) && Core\Hook::isAddonApp($this->module) && $privateapps) {
- $printNotAllowedAddon = true;
- } else {
- include_once "addon/{$this->module}/{$this->module}.php";
- if (function_exists($this->module . '_module')) {
- LegacyModule::setModuleFile("addon/{$this->module}/{$this->module}.php");
- $module_class = LegacyModule::class;
+ try {
+ $module_class = $router->getModuleClass($args->getCommand());
+ } catch (MethodNotAllowedException $e) {
+ $module_class = MethodNotAllowed::class;
+ } catch (NotFoundException $e) {
+ // Then we try addon-provided modules that we wrap in the LegacyModule class
+ if (Core\Addon::isEnabled($this->module) && file_exists("addon/{$this->module}/{$this->module}.php")) {
+ //Check if module is an app and if public access to apps is allowed or not
+ $privateapps = $config->get('config', 'private_addons', false);
+ if ((!local_user()) && Core\Hook::isAddonApp($this->module) && $privateapps) {
+ $printNotAllowedAddon = true;
+ } else {
+ include_once "addon/{$this->module}/{$this->module}.php";
+ if (function_exists($this->module . '_module')) {
+ LegacyModule::setModuleFile("addon/{$this->module}/{$this->module}.php");
+ $module_class = LegacyModule::class;
+ }
}
}
- }
- /* Finally, we look for a 'standard' program module in the 'mod' directory
- * We emulate a Module class through the LegacyModule class
- */
- if (!$module_class && file_exists("mod/{$this->module}.php")) {
- LegacyModule::setModuleFile("mod/{$this->module}.php");
- $module_class = LegacyModule::class;
- }
+ /* Finally, we look for a 'standard' program module in the 'mod' directory
+ * We emulate a Module class through the LegacyModule class
+ */
+ if (!$module_class && file_exists("mod/{$this->module}.php")) {
+ LegacyModule::setModuleFile("mod/{$this->module}.php");
+ $module_class = LegacyModule::class;
+ }
- $module_class = !isset($module_class) ? PageNotFound::class : $module_class;
+ $module_class = $module_class ?: PageNotFound::class;
+ }
return new Module($this->module, $module_class, $this->isBackend, $printNotAllowedAddon);
}
use FastRoute\RouteCollector;
use FastRoute\RouteParser\Std;
use Friendica\Core\Hook;
-use Friendica\Network\HTTPException\InternalServerErrorException;
+use Friendica\Core\L10n;
+use Friendica\Network\HTTPException;
/**
* Wrapper for FastRoute\Router
*
* @return self The router instance with the loaded routes
*
- * @throws InternalServerErrorException In case of invalid configs
+ * @throws HTTPException\InternalServerErrorException In case of invalid configs
*/
public function addRoutes(array $routes)
{
} elseif ($this->isRoute($config)) {
$routeCollector->addRoute($config[1], $route, $config[0]);
} else {
- throw new InternalServerErrorException("Wrong route config for route '" . print_r($route, true) . "'");
+ throw new HTTPException\InternalServerErrorException("Wrong route config for route '" . print_r($route, true) . "'");
}
}
} elseif ($this->isRoute($config)) {
$routeCollector->addRoute($config[1], $route, $config[0]);
}else {
- throw new InternalServerErrorException("Wrong route config for route '" . print_r($route, true) . "'");
+ throw new HTTPException\InternalServerErrorException("Wrong route config for route '" . print_r($route, true) . "'");
}
}
});
*
* @param string $cmd The path component of the request URL without the query string
*
- * @return string|null A Friendica\BaseModule-extending class name if a route rule matched
+ * @return string A Friendica\BaseModule-extending class name if a route rule matched
+ *
+ * @throws HTTPException\InternalServerErrorException
+ * @throws HTTPException\MethodNotAllowedException If a rule matched but the method didn't
+ * @throws HTTPException\NotFoundException If no rule matched
*/
public function getModuleClass($cmd)
{
$routeInfo = $dispatcher->dispatch($this->httpMethod, $cmd);
if ($routeInfo[0] === Dispatcher::FOUND) {
$moduleClass = $routeInfo[1];
+ } elseif ($routeInfo[0] === Dispatcher::METHOD_NOT_ALLOWED) {
+ throw new HTTPException\MethodNotAllowedException(L10n::t('Method not allowed for this module. Allowed method(s): %s', implode(', ', $routeInfo[1])));
+ } else {
+ throw new HTTPException\NotFoundException(L10n::t('Page not found.'));
}
return $moduleClass;
--- /dev/null
+<?php
+
+namespace Friendica\Module\HTTPException;
+
+use Friendica\BaseModule;
+use Friendica\Core\L10n;
+use Friendica\Network\HTTPException;
+
+class MethodNotAllowed extends BaseModule
+{
+ public static function content()
+ {
+ throw new HTTPException\MethodNotAllowedException(L10n::t('Method Not Allowed.'));
+ }
+}
--- /dev/null
+<?php
+
+namespace Friendica\Module\HTTPException;
+
+use Friendica\BaseModule;
+use Friendica\Core\L10n;
+use Friendica\Network\HTTPException;
+
+class PageNotFound extends BaseModule
+{
+ public static function content()
+ {
+ throw new HTTPException\NotFoundException(L10n::t('Page not found.'));
+ }
+}
+++ /dev/null
-<?php
-
-namespace Friendica\Module;
-
-use Friendica\BaseModule;
-use Friendica\Core\L10n;
-use Friendica\Network\HTTPException;
-
-class PageNotFound extends BaseModule
-{
- public static function content()
- {
- throw new HTTPException\NotFoundException(L10n::t('Page not found.'));
- }
-}
use Friendica\App;
use Friendica\Core\Config\Configuration;
use Friendica\LegacyModule;
-use Friendica\Module\PageNotFound;
+use Friendica\Module\HTTPException\PageNotFound;
use Friendica\Module\WellKnown\HostMeta;
use Friendica\Test\DatabaseTest;
{
$module = new App\Module();
- $moduleNew = $module->determineModule(new App\Arguments(), []);
+ $moduleNew = $module->determineModule(new App\Arguments());
$this->assertNotSame($moduleNew, $module);
}
use Friendica\App\Router;
use Friendica\Module;
+use Friendica\Network\HTTPException\MethodNotAllowedException;
+use Friendica\Network\HTTPException\NotFoundException;
use PHPUnit\Framework\TestCase;
class RouterTest extends TestCase
{
public function testGetModuleClass()
{
- $router = new Router(['GET']);
+ $router = new Router(['REQUEST_METHOD' => 'GET']);
$routeCollector = $router->getRouteCollector();
$routeCollector->addRoute(['GET'], '/', 'IndexModuleClassName');
$routeCollector->addRoute(['POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'], '/unsupported', 'UnsupportedMethodModuleClassName');
$this->assertEquals('IndexModuleClassName', $router->getModuleClass('/'));
-
$this->assertEquals('TestModuleClassName', $router->getModuleClass('/test'));
- $this->assertNull($router->getModuleClass('/tes'));
-
$this->assertEquals('TestSubModuleClassName', $router->getModuleClass('/test/sub'));
-
$this->assertEquals('OptionalModuleClassName', $router->getModuleClass('/optional'));
$this->assertEquals('OptionalModuleClassName', $router->getModuleClass('/optional/option'));
- $this->assertNull($router->getModuleClass('/optional/opt'));
-
$this->assertEquals('VariableModuleClassName', $router->getModuleClass('/variable/123abc'));
- $this->assertNull($router->getModuleClass('/variable'));
-
$this->assertEquals('OptionalVariableModuleClassName', $router->getModuleClass('/optionalvariable'));
$this->assertEquals('OptionalVariableModuleClassName', $router->getModuleClass('/optionalvariable/123abc'));
+ }
+
+ public function testGetModuleClassNotFound()
+ {
+ $this->expectException(NotFoundException::class);
+
+ $router = new Router(['REQUEST_METHOD' => 'GET']);
+
+ $router->getModuleClass('/unsupported');
+ }
+
+ public function testGetModuleClassNotFoundTypo()
+ {
+ $this->expectException(NotFoundException::class);
+
+ $router = new Router(['REQUEST_METHOD' => 'GET']);
+
+ $routeCollector = $router->getRouteCollector();
+ $routeCollector->addRoute(['GET'], '/test', 'TestModuleClassName');
+
+ $router->getModuleClass('/tes');
+ }
+
+ public function testGetModuleClassNotFoundOptional()
+ {
+ $this->expectException(NotFoundException::class);
+
+ $router = new Router(['REQUEST_METHOD' => 'GET']);
+
+ $routeCollector = $router->getRouteCollector();
+ $routeCollector->addRoute(['GET'], '/optional[/option]', 'OptionalModuleClassName');
+
+ $router->getModuleClass('/optional/opt');
+ }
+
+ public function testGetModuleClassNotFoundVariable()
+ {
+ $this->expectException(NotFoundException::class);
+
+ $router = new Router(['REQUEST_METHOD' => 'GET']);
+
+ $routeCollector = $router->getRouteCollector();
+ $routeCollector->addRoute(['GET'], '/variable/{var}', 'VariableModuleClassName');
+
+ $router->getModuleClass('/variable');
+ }
+
+ public function testGetModuleClassMethodNotAllowed()
+ {
+ $this->expectException(MethodNotAllowedException::class);
+
+ $router = new Router(['REQUEST_METHOD' => 'POST']);
+
+ $routeCollector = $router->getRouteCollector();
+ $routeCollector->addRoute(['GET'], '/test', 'TestModuleClassName');
- $this->assertNull($router->getModuleClass('/unsupported'));
+ $router->getModuleClass('/test');
}
public function dataRoutes()