|
|
|
@ -4,23 +4,31 @@ namespace BitCommunism\Http;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use DI\Container;
|
|
|
|
|
use DI\ContainerBuilder;
|
|
|
|
|
use function DI\value;
|
|
|
|
|
use FastRoute\Dispatcher;
|
|
|
|
|
use FastRoute\RouteCollector;
|
|
|
|
|
use function FastRoute\simpleDispatcher;
|
|
|
|
|
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 Invoker\Invoker;
|
|
|
|
|
use Invoker\ParameterResolver\AssociativeArrayResolver;
|
|
|
|
|
use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
|
|
|
|
|
use Invoker\ParameterResolver\DefaultValueResolver;
|
|
|
|
|
use Invoker\ParameterResolver\NumericArrayResolver;
|
|
|
|
|
use Invoker\ParameterResolver\ResolverChain;
|
|
|
|
|
use Invoker\ParameterResolver\TypeHintResolver;
|
|
|
|
|
use Psr\Http\Message\ResponseInterface;
|
|
|
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
|
|
|
use function FastRoute\simpleDispatcher;
|
|
|
|
|
use function GuzzleHttp\Psr7\copy_to_stream;
|
|
|
|
|
use function GuzzleHttp\Psr7\stream_for;
|
|
|
|
|
|
|
|
|
|
class Server
|
|
|
|
|
{
|
|
|
|
|
private $routes = [];
|
|
|
|
|
private $container;
|
|
|
|
|
/**
|
|
|
|
|
* @var Invoker
|
|
|
|
|
*/
|
|
|
|
|
private $invoker;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var Dispatcher
|
|
|
|
@ -31,6 +39,7 @@ class Server
|
|
|
|
|
{
|
|
|
|
|
$this->routes = $routes;
|
|
|
|
|
$this->container = $container;
|
|
|
|
|
$this->invoker = $this->createDefaultInvoker();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function iterateRoutes()
|
|
|
|
@ -40,17 +49,26 @@ class Server
|
|
|
|
|
|
|
|
|
|
private function iterateRoutesFromArray($routeArr, $prefix = '', $known = [], $middleware = [])
|
|
|
|
|
{
|
|
|
|
|
$route = $routeArr['middleware'] ?? [];
|
|
|
|
|
$middleware = array_merge($middleware, array_map(function ($route) {
|
|
|
|
|
if (!$route instanceof Handle) {
|
|
|
|
|
return new Handle($route);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $route;
|
|
|
|
|
}, (array)$route));
|
|
|
|
|
|
|
|
|
|
foreach ($routeArr as $key => $route) {
|
|
|
|
|
if ($key === 'middleware') {
|
|
|
|
|
$middleware = array_merge($middleware, $route);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_array($route) && !(isset($route[0]) && isset($route[1]))) {
|
|
|
|
|
yield from $this->iterateRoutesFromArray($route, $prefix . $key, $known);
|
|
|
|
|
yield from $this->iterateRoutesFromArray($route, $prefix . $key, $known, $middleware);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_array($route) || is_string($route)) {
|
|
|
|
|
if (!$route instanceof Handle) {
|
|
|
|
|
$route = new Handle($route);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -123,6 +141,16 @@ class Server
|
|
|
|
|
return $response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function createDefaultInvoker() {
|
|
|
|
|
return new Invoker(new ResolverChain(array(
|
|
|
|
|
new NumericArrayResolver(),
|
|
|
|
|
new AssociativeArrayResolver(),
|
|
|
|
|
new DefaultValueResolver(),
|
|
|
|
|
new TypeHintResolver(),
|
|
|
|
|
new TypeHintContainerResolver($this->container),
|
|
|
|
|
)), $this->container);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function handleHttp(ServerRequestInterface $request, Handle $handler, array $vars, ResponseInterface $response = null): ResponseInterface
|
|
|
|
|
{
|
|
|
|
|
$middlewareArray = $handler->getMiddleware();
|
|
|
|
@ -134,29 +162,33 @@ class Server
|
|
|
|
|
$response = new Response(200, [], stream_for('Empty response'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$context = new Context($request, $response);
|
|
|
|
|
$context = new Context($request, $response, $vars);
|
|
|
|
|
|
|
|
|
|
$next = function (Context $context) use ($handler, $middlewareArray, &$middlewarePointer, &$next) {
|
|
|
|
|
$output = null;
|
|
|
|
|
|
|
|
|
|
if (count($middlewareArray) >= $middlewarePointer) {
|
|
|
|
|
$call = $handler->getCall();
|
|
|
|
|
if (is_array($call)) {
|
|
|
|
|
$obj = $this->container->get($call[0]);
|
|
|
|
|
$call = [$obj, $call[1]];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
[$name, $func] = $middlewareArray[$middlewarePointer++];
|
|
|
|
|
$middleware = $this->container->get($name);
|
|
|
|
|
$call = [$middleware, $func];
|
|
|
|
|
if (count($middlewareArray) > $middlewarePointer) {
|
|
|
|
|
$handler = $middlewareArray[$middlewarePointer++];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$call = $handler->getCall();
|
|
|
|
|
if (is_array($call)) {
|
|
|
|
|
$obj = $this->container->get($call[0]);
|
|
|
|
|
$call = [$obj, $call[1]];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$output = $this->container->call($call, [
|
|
|
|
|
$context->setSettings($handler->getSettings());
|
|
|
|
|
|
|
|
|
|
$output = $this->invoker->call($call, [
|
|
|
|
|
'request' => $context->getRequest(),
|
|
|
|
|
ServerRequestInterface::class => $context->getRequest(),
|
|
|
|
|
'response' => $context->getResponse(),
|
|
|
|
|
ResponseInterface::class => $context->getResponse(),
|
|
|
|
|
'context' => $context,
|
|
|
|
|
Context::class => $context,
|
|
|
|
|
'vars' => $context->getVars(),
|
|
|
|
|
'settings' => $context->getSettings(),
|
|
|
|
|
'next' => $next,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$this->normalizeResponse($output, $context);
|
|
|
|
@ -169,6 +201,10 @@ class Server
|
|
|
|
|
|
|
|
|
|
private function normalizeResponse($response, Context $context)
|
|
|
|
|
{
|
|
|
|
|
if ($response === null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($response instanceof ResponseInterface) {
|
|
|
|
|
$context->setResponse($response);
|
|
|
|
|
return;
|
|
|
|
|