diff options
Diffstat (limited to 'src/Router')
| -rw-r--r-- | src/Router/Router.php | 85 | ||||
| -rw-r--r-- | src/Router/routes_client_server.php | 41 | ||||
| -rw-r--r-- | src/Router/routes_server_server.php | 24 | 
3 files changed, 150 insertions, 0 deletions
diff --git a/src/Router/Router.php b/src/Router/Router.php new file mode 100644 index 0000000..b167142 --- /dev/null +++ b/src/Router/Router.php @@ -0,0 +1,85 @@ +<?php + +namespace App\Router; + +use App\Errors\ErrorCode; +use App\Errors\ErrorResponse; +use App\Errors\Exception; +use App\Singleton; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +class Router +{ +  use Singleton; + +  private RouteCollection $routes; +  private RouteConfigurator $configurator; + +  public function __construct() +  { +    $this->routes = new RouteCollection(); +    $this->configurator = new RouteConfigurator($this->routes, $this->routes); + +    $this->addRoutes(); +  } + +  /** +   * match the current url against the routes. +   * also add preflight CORS headers on OPTIONS requests. +   */ +  public function run(): Response +  { +    $request = Request::createFromGlobals(); + +    if ($request->isMethod("OPTIONS")) { +      $response = new Response(); +      $response->headers->add([ +        "Access-Control-Allow-Origin" => "*", +        "Access-Control-Allow-Methods" => "GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD", +        "Access-Control-Allow-Headers" => "X-Requested-With, Content-Type, Authorization", +      ]); + +      return $response; +    } + +    $context = new RequestContext(); +    $context->fromRequest($request); + +    try { +      $matcher = new UrlMatcher($this->routes, $context); +      $match = $matcher->matchRequest($request); + +      $class = $match["_controller"][0]; +      $method = $match["_controller"][1]; + +      return (new $class)->$method(); +    } catch (Exception $exception) { +      return ErrorResponse::fromException($exception); +    } catch (ResourceNotFoundException $exception) { +      return new ErrorResponse(ErrorCode::NOT_FOUND, "404", Response::HTTP_NOT_FOUND); +    } catch (MethodNotAllowedException $exception) { +      return new ErrorResponse(ErrorCode::FORBIDDEN, "403", Response::HTTP_FORBIDDEN); +    } catch (\Exception $exception) { +      return new ErrorResponse(ErrorCode::UNKNOWN, "Unknown error occured", Response::HTTP_INTERNAL_SERVER_ERROR); +    } +  } + +  /** +   * add routes from the routes file +   */ +  private function addRoutes(): void +  { +    $routesClientServer = include_once(__DIR__ . "/routes_client_server.php"); +    $routesClientServer($this->configurator); + +    $routesServerServer = include_once(__DIR__ . "/routes_server_server.php"); +    $routesServerServer($this->configurator); +  } +} diff --git a/src/Router/routes_client_server.php b/src/Router/routes_client_server.php new file mode 100644 index 0000000..eff0be5 --- /dev/null +++ b/src/Router/routes_client_server.php @@ -0,0 +1,41 @@ +<?php + +namespace App\Router; + +use App\Controllers\LoginController; +use App\Controllers\ServerDiscoveryController; +use App\Controllers\ServerImplementationController; +use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; + +return function (RouteConfigurator $routes): void +{ +  $routes +    ->add("well_known_matrix_client", "/.well-known/matrix/client") +    ->controller([ServerDiscoveryController::class, "client"]) +    ->methods(["GET"]); + +  $routes +    ->add("well_known_matrix_support", "/.well-known/matrix/support") +    ->controller([ServerDiscoveryController::class, "support"]) +    ->methods(["GET"]); + +  $routes +    ->add("matrix_client_versions", "/_matrix/client/versions") +    ->controller([ServerImplementationController::class, "versions"]) +    ->methods(["GET"]); + +  $supportedLoginTypes = [LoginController::class, "supportedLoginTypes"]; +  $routes +    ->add("matrix_client_r0_login_types", "/_matrix/client/r0/login") +    ->controller($supportedLoginTypes) +    ->methods(["GET"]); +  $routes +    ->add("matrix_client_v3_login_types", "/_matrix/client/v3/login") +    ->controller($supportedLoginTypes) +    ->methods(["GET"]); + +  $routes +    ->add("matrix_client_v3_login", "/_matrix/client/v3/login") +    ->controller([LoginController::class, "login"]) +    ->methods(["POST"]); +}; diff --git a/src/Router/routes_server_server.php b/src/Router/routes_server_server.php new file mode 100644 index 0000000..2e85a17 --- /dev/null +++ b/src/Router/routes_server_server.php @@ -0,0 +1,24 @@ +<?php + +namespace App\Router; + +use App\Controllers\ServerDiscoveryController; +use App\Controllers\ServerImplementationController; +use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; + +return function (RouteConfigurator $routes): void +{ +  $routes +    ->add("well_known_matrix_server", "/.well-known/matrix/server") +    ->controller([ServerDiscoveryController::class, "server"]) +    ->methods(["GET"]); + +  $routes +    ->add("matrix_federation_version", "/_matrix/federation/v1/version") +    ->controller([ServerImplementationController::class, "version"]) +    ->methods(["GET"]); + +  # /_matrix/key/v2/server +  # /_matrix/key/v2/query +  # /_matrix/key/v2/query/{serverName} +};  | 
