diff --git a/composer.json b/composer.json index 4586b24..a1a5c53 100644 --- a/composer.json +++ b/composer.json @@ -11,4 +11,4 @@ "BitCommunism\\Http\\": "src/" } } -} +} \ No newline at end of file diff --git a/config/default.php b/config/default.php index 9d4eb66..533c428 100644 --- a/config/default.php +++ b/config/default.php @@ -10,7 +10,7 @@ use function DI\object; return [ 'marx.calls' => add([ 'http' => function(Server $server) { - $server->serve(); + return $server; } ]), diff --git a/src/Server.php b/src/Server.php index b1753d5..376a888 100644 --- a/src/Server.php +++ b/src/Server.php @@ -17,6 +17,7 @@ use function GuzzleHttp\Psr7\copy_to_stream; use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\ServerRequest; use function GuzzleHttp\Psr7\stream_for; +use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; @@ -24,6 +25,10 @@ class Server { private $routes = []; private $container; + + /** + * @var Dispatcher + */ private $router; public function __construct($routes, Container $container) @@ -78,30 +83,10 @@ class Server public function serve() { $request = ServerRequest::fromGlobals(); - $path = $request->getUri()->getPath(); - $method = $request->getMethod(); - $routeInfo = $this->router->dispatch($method, $path); - $response = null; + $response = $this->respond($request); - switch ($routeInfo[0]) { - case Dispatcher::NOT_FOUND: - // todo: Error page - break; - case Dispatcher::METHOD_NOT_ALLOWED: - // todo: Error page - break; - case Dispatcher::FOUND: - [$_, $handler, $vars] = $routeInfo; - $response = $this->handleHttp($request, $handler, $vars); - break; - } - - if ($response === null) { - // todo: Error page - } - - header('Status: ' . $response->getStatusCode() . ' ' . $response->getReasonPhrase()); + header('HTTP/' . $response->getProtocolVersion() . ' ' . $response->getStatusCode() . ' ' . $response->getReasonPhrase()); $wrote = []; foreach ($response->getHeaders() as [$headerName, $headerValue]) { @@ -115,36 +100,73 @@ class Server copy_to_stream($response->getBody(), stream_for($stdout)); } - public function handleHttp(ServerRequestInterface $request, array $handler, array $vars): ResponseInterface + public function respond(ServerRequestInterface $request, ResponseInterface $response = null): ResponseInterface + { + $path = $request->getUri()->getPath(); + $method = $request->getMethod(); + $routeInfo = $this->router->dispatch($method, $path); + + switch ($routeInfo[0]) { + case Dispatcher::NOT_FOUND: + // todo: Error page + break; + case Dispatcher::METHOD_NOT_ALLOWED: + // todo: Error page + break; + case Dispatcher::FOUND: + [$_, $handler, $vars] = $routeInfo; + $response = $this->handleHttp($request, $handler, $vars, $response); + break; + } + + if ($response === null) { + // todo: Error page + } + + return $response; + } + + public function handleHttp(ServerRequestInterface $request, array $handler, array $vars, ResponseInterface $response = null): ResponseInterface { [$_, $_, $middlewareArray] = $handler; $middlewarePointer = 0; $next = null; - $response = new Response(200, [], stream_for('No answer')); + + if ($response === null) { + $response = new Response(200, [], stream_for('No answer')); + } $next = function ($request, $response, $vars) use ($handler, $middlewareArray, &$middlewarePointer, &$next) { $output = null; if (count($middlewareArray) >= $middlewarePointer) { $obj = $this->container->get($handler[0]); - $output = $obj->{$handler[1]}($request, $response, $vars); + $call = [$obj, $handler[1]]; } else { - [$name, $func] = $middlewareArray[$middlewarePointer++]; - $middleware = $this->container->get($name); - $output = $middleware->{$func}($request, $response, $vars); + $call = [$middleware, $func]; } + $output = $this->container->call($call, [ + RequestInterface::class => $request, + ResponseInterface::class => $response, + 'request' => $request, + 'response' => $response, + 'vars' => $vars, + ]); + + return $this->normalizeResponse($output, $response); }; return $next($request, $response, $vars); } - private function normalizeResponse($response, ResponseInterface $previousResponse) { + private function normalizeResponse($response, ResponseInterface $previousResponse) + { if ($response instanceof ResponseInterface) { return $response; }