summaryrefslogtreecommitdiff
path: root/src/Router/Router.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Router/Router.php')
-rw-r--r--src/Router/Router.php85
1 files changed, 85 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);
+ }
+}