This commit is contained in:
lubiana 2022-03-31 08:34:30 +02:00
parent 7052803761
commit bb13950966
Signed by: lubiana
SSH key fingerprint: SHA256:vW1EA0fRR3Fw+dD/sM0K+x3Il2gSry6YRYHqOeQwrfk
107 changed files with 8372 additions and 186 deletions

View file

@ -63,7 +63,7 @@ final class CachingMiddleware implements MiddlewareInterface
public function __construct(private CacheInterface $cache){}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
if ($request->getAttribute('isAuthenticated', false)) {
if ($request->getAttribute('isAuthenticated', false) && $request->getMethod() === 'GET') {
$key = $request->getUri()->getPath();
return $this->cache->get($key, fn() => $handler->handle($request), 10);
}
@ -135,16 +135,33 @@ interface Pipeline
And our implementation looks something like this:
```php
final class SimplePipeline implements Pipeline
<?php declare(strict_types=1);
namespace Lubian\NoFramework\Http;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use function array_reverse;
use function assert;
use function is_string;
class ContainerPipeline implements Pipeline
{
/**
* @param MiddlewareInterface[] $middlewares
* @param RequestHandlerInterface $tip
*/
* @param array<MiddlewareInterface|class-string> $middlewares
* @param RequestHandlerInterface $tip
* @param ContainerInterface $container
*/
public function __construct(
private readonly array $middlewares,
private RequestHandlerInterface $tip
){}
private array $middlewares,
private RequestHandlerInterface $tip,
private ContainerInterface $container,
) {
}
public function dispatch(ServerRequestInterface $request): ResponseInterface
{
@ -156,19 +173,49 @@ final class SimplePipeline implements Pipeline
{
foreach (array_reverse($this->middlewares) as $middleware) {
$next = $this->tip;
$this->tip = new class ($middleware, $next) implements RequestHandlerInterface {
public function __construct(
private readonly MiddlewareInterface $middleware,
private readonly RequestHandlerInterface $next
){}
public function handle(ServerRequestInterface $request): ResponseInterface
{
return $this->middleware->process($request, $this->next);
}
};
if ($middleware instanceof MiddlewareInterface) {
$this->tip = $this->wrapMiddleware($middleware, $next);
}
if (is_string($middleware)) {
$this->tip = $this->wrapResolvedMiddleware($middleware, $next);
}
}
}
private function wrapResolvedMiddleware(string $middleware, RequestHandlerInterface $next): RequestHandlerInterface
{
return new class ($middleware, $next, $this->container) implements RequestHandlerInterface {
public function __construct(
private readonly string $middleware,
private readonly RequestHandlerInterface $handler,
private readonly ContainerInterface $container,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$middleware = $this->container->get($this->middleware);
assert($middleware instanceof MiddlewareInterface);
return $middleware->process($request, $this->handler);
}
};
}
private function wrapMiddleware(MiddlewareInterface $middleware, RequestHandlerInterface $next): RequestHandlerInterface
{
return new class ($middleware, $next) implements RequestHandlerInterface {
public function __construct(
private readonly MiddlewareInterface $middleware,
private readonly RequestHandlerInterface $handler,
) {
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
return $this->middleware->process($request, $this->handler);
}
};
}
}
```
@ -180,27 +227,58 @@ and store that itself as the current tip.
There are of course a lot of more sophisticated ways to build a pipeline/dispatcher that you can check out at the [middlewares github](https://github.com/middlewares/awesome-psr15-middlewares#dispatcher)
Lets add a simple factory to our dependencies.php file that creates our middlewarepipeline:
Lets add a simple factory to our dependencies.php file that creates our middlewarepipeline
Lets create a simple Factory that loads an Array of Middlewares from the Config folder and uses that to build our pipeline
```php
Pipeline::class => function (
RouteDecoratedRequestHandler $tip,
RouteDecorationMiddleware $router,
) {
$middlewares = require __DIR__ . '/middlewares.php';
$middlewares[] = $router;
return new SimplePipeline($middlewares, $tip);
},
<?php declare(strict_types=1);
namespace Lubian\NoFramework\Factory;
use Lubian\NoFramework\Http\ContainerPipeline;
use Lubian\NoFramework\Http\Pipeline;
use Lubian\NoFramework\Http\RoutedRequestHandler;
use Lubian\NoFramework\Settings;
use Psr\Container\ContainerInterface;
class PipelineProvider
{
public function __construct(
private Settings $settings,
private RoutedRequestHandler $tip,
private ContainerInterface $container,
) {
}
public function getPipeline(): Pipeline
{
$middlewares = require $this->settings->middlewaresFile;
return new ContainerPipeline($middlewares, $this->tip, $this->container);
}
}
```
And configure the container to use the Factory to create the Pipeline:
```php
...,
Pipeline::class => fn (PipelineProvider $p) => $p->getPipeline(),
...
```
And of course a new file called middlewares.php in our config folder:
```php
<?php
<?php declare(strict_types=1);
declare(strict_types=1);
use Lubian\NoFramework\Http\RouteMiddleware;
use Middlewares\TrailingSlash;
use Middlewares\Whoops;
return [
new \Middlewares\Whoops(),
new \Middlewares\TrailingSlash(),
Whoops::class,
TrailingSlash::class,
RouteMiddleware::class,
];
```
And we need to add the pipeline to our Kernel class. I will leave that as an exercise to you, a simple hint that i can