Use PSR-15 middleware standard

This finally adopts the new standardized interfaces instead of the
work-in-progress ones with the `Interop\` prefix.

Since we have now updated to PHP 7.1, we can also use Stratigility
3.0 as the middleware dispatcher.
This commit is contained in:
Franz Liedke 2018-05-29 00:17:13 +02:00
parent 5d0ebde6b8
commit 3680d88fb7
No known key found for this signature in database
GPG Key ID: 9A0231A879B055F4
15 changed files with 101 additions and 96 deletions

View File

@ -47,6 +47,8 @@
"nikic/fast-route": "^0.6", "nikic/fast-route": "^0.6",
"oyejorge/less.php": "~1.5", "oyejorge/less.php": "~1.5",
"psr/http-message": "^1.0", "psr/http-message": "^1.0",
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"symfony/config": "^3.3", "symfony/config": "^3.3",
"symfony/console": "^3.3", "symfony/console": "^3.3",
"symfony/http-foundation": "^3.3", "symfony/http-foundation": "^3.3",
@ -54,9 +56,8 @@
"symfony/yaml": "^3.3", "symfony/yaml": "^3.3",
"s9e/text-formatter": "^0.8.1", "s9e/text-formatter": "^0.8.1",
"tobscure/json-api": "^0.3.0", "tobscure/json-api": "^0.3.0",
"zendframework/zend-diactoros": "^1.6", "zendframework/zend-diactoros": "^1.7",
"zendframework/zend-stratigility": "^2.2", "zendframework/zend-stratigility": "^3.0"
"http-interop/http-middleware": "^0.4.0"
}, },
"require-dev": { "require-dev": {
"mockery/mockery": "^0.9.4", "mockery/mockery": "^0.9.4",

View File

@ -12,18 +12,19 @@
namespace Flarum\Admin\Middleware; namespace Flarum\Admin\Middleware;
use Flarum\User\AssertPermissionTrait; use Flarum\User\AssertPermissionTrait;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class RequireAdministrateAbility implements MiddlewareInterface class RequireAdministrateAbility implements Middleware
{ {
use AssertPermissionTrait; use AssertPermissionTrait;
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$this->assertAdmin($request->getAttribute('actor')); $this->assertAdmin($request->getAttribute('actor'));
return $delegate->process($request); return $handler->handle($request);
} }
} }

View File

@ -11,15 +11,16 @@
namespace Flarum\Api\Middleware; namespace Flarum\Api\Middleware;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class FakeHttpMethods implements MiddlewareInterface class FakeHttpMethods implements Middleware
{ {
const HEADER_NAME = 'x-http-method-override'; const HEADER_NAME = 'x-http-method-override';
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
if ($request->getMethod() === 'POST' && $request->hasHeader(self::HEADER_NAME)) { if ($request->getMethod() === 'POST' && $request->hasHeader(self::HEADER_NAME)) {
$fakeMethod = $request->getHeaderLine(self::HEADER_NAME); $fakeMethod = $request->getHeaderLine(self::HEADER_NAME);
@ -27,6 +28,6 @@ class FakeHttpMethods implements MiddlewareInterface
$request = $request->withMethod(strtoupper($fakeMethod)); $request = $request->withMethod(strtoupper($fakeMethod));
} }
return $delegate->process($request); return $handler->handle($request);
} }
} }

View File

@ -13,12 +13,12 @@ namespace Flarum\Api\Middleware;
use Exception; use Exception;
use Flarum\Api\ErrorHandler; use Flarum\Api\ErrorHandler;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class HandleErrors implements MiddlewareInterface class HandleErrors implements Middleware
{ {
/** /**
* @var ErrorHandler * @var ErrorHandler
@ -35,15 +35,11 @@ class HandleErrors implements MiddlewareInterface
/** /**
* Catch all errors that happen during further middleware execution. * Catch all errors that happen during further middleware execution.
*
* @param Request $request
* @param DelegateInterface $delegate
* @return Response
*/ */
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
try { try {
return $delegate->process($request); return $handler->handle($request);
} catch (Exception $e) { } catch (Exception $e) {
return $this->errorHandler->handle($e); return $this->errorHandler->handle($e);
} }

View File

@ -14,15 +14,16 @@ namespace Flarum\Http\Middleware;
use Flarum\Api\ApiKey; use Flarum\Api\ApiKey;
use Flarum\Http\AccessToken; use Flarum\Http\AccessToken;
use Flarum\User\User; use Flarum\User\User;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class AuthenticateWithHeader implements MiddlewareInterface class AuthenticateWithHeader implements Middleware
{ {
const TOKEN_PREFIX = 'Token '; const TOKEN_PREFIX = 'Token ';
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$headerLine = $request->getHeaderLine('authorization'); $headerLine = $request->getHeaderLine('authorization');
@ -50,7 +51,7 @@ class AuthenticateWithHeader implements MiddlewareInterface
} }
} }
return $delegate->process($request); return $handler->handle($request);
} }
private function getUser($string) private function getUser($string)

View File

@ -14,13 +14,14 @@ namespace Flarum\Http\Middleware;
use Flarum\User\Guest; use Flarum\User\Guest;
use Flarum\User\User; use Flarum\User\User;
use Illuminate\Contracts\Session\Session; use Illuminate\Contracts\Session\Session;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class AuthenticateWithSession implements MiddlewareInterface class AuthenticateWithSession implements Middleware
{ {
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$session = $request->getAttribute('session'); $session = $request->getAttribute('session');
@ -30,7 +31,7 @@ class AuthenticateWithSession implements MiddlewareInterface
$request = $request->withAttribute('actor', $actor); $request = $request->withAttribute('actor', $actor);
return $delegate->process($request); return $handler->handle($request);
} }
private function getActor(Session $session) private function getActor(Session $session)

View File

@ -16,12 +16,13 @@ use Flarum\User\AuthToken;
use Flarum\User\EmailToken; use Flarum\User\EmailToken;
use Flarum\User\PasswordToken; use Flarum\User\PasswordToken;
use Illuminate\Contracts\Config\Repository as ConfigRepository; use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
use SessionHandlerInterface; use SessionHandlerInterface;
class CollectGarbage implements MiddlewareInterface class CollectGarbage implements Middleware
{ {
/** /**
* @var SessionHandlerInterface * @var SessionHandlerInterface
@ -39,11 +40,11 @@ class CollectGarbage implements MiddlewareInterface
$this->sessionConfig = $config->get('session'); $this->sessionConfig = $config->get('session');
} }
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$this->collectGarbageSometimes(); $this->collectGarbageSometimes();
return $delegate->process($request); return $handler->handle($request);
} }
private function collectGarbageSometimes() private function collectGarbageSometimes()

View File

@ -15,12 +15,12 @@ use FastRoute\Dispatcher;
use Flarum\Http\Exception\MethodNotAllowedException; use Flarum\Http\Exception\MethodNotAllowedException;
use Flarum\Http\Exception\RouteNotFoundException; use Flarum\Http\Exception\RouteNotFoundException;
use Flarum\Http\RouteCollection; use Flarum\Http\RouteCollection;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class DispatchRoute implements MiddlewareInterface class DispatchRoute implements Middleware
{ {
/** /**
* @var RouteCollection * @var RouteCollection
@ -45,13 +45,10 @@ class DispatchRoute implements MiddlewareInterface
/** /**
* Dispatch the given request to our route collection. * Dispatch the given request to our route collection.
* *
* @param Request $request
* @param DelegateInterface $delegate
* @return Response
* @throws MethodNotAllowedException * @throws MethodNotAllowedException
* @throws RouteNotFoundException * @throws RouteNotFoundException
*/ */
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$method = $request->getMethod(); $method = $request->getMethod();
$uri = $request->getUri()->getPath() ?: '/'; $uri = $request->getUri()->getPath() ?: '/';

View File

@ -15,15 +15,15 @@ use Exception;
use Flarum\Settings\SettingsRepositoryInterface; use Flarum\Settings\SettingsRepositoryInterface;
use Franzl\Middleware\Whoops\WhoopsRunner; use Franzl\Middleware\Whoops\WhoopsRunner;
use Illuminate\Contracts\View\Factory as ViewFactory; use Illuminate\Contracts\View\Factory as ViewFactory;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use Zend\Diactoros\Response\HtmlResponse; use Zend\Diactoros\Response\HtmlResponse;
class HandleErrors implements MiddlewareInterface class HandleErrors implements Middleware
{ {
/** /**
* @var ViewFactory * @var ViewFactory
@ -68,15 +68,11 @@ class HandleErrors implements MiddlewareInterface
/** /**
* Catch all errors that happen during further middleware execution. * Catch all errors that happen during further middleware execution.
*
* @param Request $request
* @param DelegateInterface $delegate
* @return Response
*/ */
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
try { try {
return $delegate->process($request); return $handler->handle($request);
} catch (Exception $e) { } catch (Exception $e) {
if ($this->debug) { if ($this->debug) {
return WhoopsRunner::handle($e, $request); return WhoopsRunner::handle($e, $request);

View File

@ -11,13 +11,14 @@
namespace Flarum\Http\Middleware; namespace Flarum\Http\Middleware;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class ParseJsonBody implements MiddlewareInterface class ParseJsonBody implements Middleware
{ {
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
if (str_contains($request->getHeaderLine('content-type'), 'json')) { if (str_contains($request->getHeaderLine('content-type'), 'json')) {
$input = json_decode($request->getBody(), true); $input = json_decode($request->getBody(), true);
@ -25,6 +26,6 @@ class ParseJsonBody implements MiddlewareInterface
$request = $request->withParsedBody($input ?: []); $request = $request->withParsedBody($input ?: []);
} }
return $delegate->process($request); return $handler->handle($request);
} }
} }

View File

@ -13,11 +13,12 @@ namespace Flarum\Http\Middleware;
use Flarum\Http\AccessToken; use Flarum\Http\AccessToken;
use Flarum\Http\CookieFactory; use Flarum\Http\CookieFactory;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class RememberFromCookie implements MiddlewareInterface class RememberFromCookie implements Middleware
{ {
/** /**
* @var CookieFactory * @var CookieFactory
@ -32,7 +33,7 @@ class RememberFromCookie implements MiddlewareInterface
$this->cookie = $cookie; $this->cookie = $cookie;
} }
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$id = array_get($request->getCookieParams(), $this->cookie->getName('remember')); $id = array_get($request->getCookieParams(), $this->cookie->getName('remember'));
@ -48,6 +49,6 @@ class RememberFromCookie implements MiddlewareInterface
} }
} }
return $delegate->process($request); return $handler->handle($request);
} }
} }

View File

@ -12,11 +12,12 @@
namespace Flarum\Http\Middleware; namespace Flarum\Http\Middleware;
use Flarum\Locale\LocaleManager; use Flarum\Locale\LocaleManager;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class SetLocale implements MiddlewareInterface class SetLocale implements Middleware
{ {
/** /**
* @var LocaleManager * @var LocaleManager
@ -31,7 +32,7 @@ class SetLocale implements MiddlewareInterface
$this->locales = $locales; $this->locales = $locales;
} }
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$actor = $request->getAttribute('actor'); $actor = $request->getAttribute('actor');
@ -45,6 +46,6 @@ class SetLocale implements MiddlewareInterface
$this->locales->setLocale($locale); $this->locales->setLocale($locale);
} }
return $delegate->process($request); return $handler->handle($request);
} }
} }

View File

@ -13,16 +13,17 @@ namespace Flarum\Http\Middleware;
use Illuminate\Contracts\View\Factory as ViewFactory; use Illuminate\Contracts\View\Factory as ViewFactory;
use Illuminate\Support\ViewErrorBag; use Illuminate\Support\ViewErrorBag;
use Interop\Http\ServerMiddleware\DelegateInterface; use Psr\Http\Message\ResponseInterface as Response;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
/** /**
* Inspired by Illuminate\View\Middleware\ShareErrorsFromSession. * Inspired by Illuminate\View\Middleware\ShareErrorsFromSession.
* *
* @author Taylor Otwell * @author Taylor Otwell
*/ */
class ShareErrorsFromSession implements MiddlewareInterface class ShareErrorsFromSession implements Middleware
{ {
/** /**
* @var ViewFactory * @var ViewFactory
@ -37,7 +38,7 @@ class ShareErrorsFromSession implements MiddlewareInterface
$this->view = $view; $this->view = $view;
} }
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$session = $request->getAttribute('session'); $session = $request->getAttribute('session');
@ -54,6 +55,6 @@ class ShareErrorsFromSession implements MiddlewareInterface
$session->remove('errors'); $session->remove('errors');
return $delegate->process($request); return $handler->handle($request);
} }
} }

View File

@ -16,13 +16,13 @@ use Flarum\Http\CookieFactory;
use Illuminate\Contracts\Config\Repository as ConfigRepository; use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Illuminate\Contracts\Session\Session; use Illuminate\Contracts\Session\Session;
use Illuminate\Session\Store; use Illuminate\Session\Store;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
use SessionHandlerInterface; use SessionHandlerInterface;
class StartSession implements MiddlewareInterface class StartSession implements Middleware
{ {
/** /**
* @var SessionHandlerInterface * @var SessionHandlerInterface
@ -51,7 +51,7 @@ class StartSession implements MiddlewareInterface
$this->config = $config->get('session'); $this->config = $config->get('session');
} }
public function process(Request $request, DelegateInterface $delegate) public function process(Request $request, Handler $handler): Response
{ {
$request = $request->withAttribute( $request = $request->withAttribute(
'session', 'session',
@ -59,7 +59,7 @@ class StartSession implements MiddlewareInterface
); );
$session->start(); $session->start();
$response = $delegate->process($request); $response = $handler->handle($request);
$session->save(); $session->save();
$response = $this->withCsrfTokenHeader($response, $session); $response = $this->withCsrfTokenHeader($response, $session);

View File

@ -18,16 +18,17 @@ use Flarum\Http\Middleware\HandleErrors;
use Flarum\Http\Middleware\StartSession; use Flarum\Http\Middleware\StartSession;
use Flarum\Install\InstallServiceProvider; use Flarum\Install\InstallServiceProvider;
use Flarum\Update\UpdateServiceProvider; use Flarum\Update\UpdateServiceProvider;
use Interop\Http\ServerMiddleware\MiddlewareInterface; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
use Zend\Diactoros\Response\HtmlResponse; use Zend\Diactoros\Response\HtmlResponse;
use Zend\Diactoros\Server as DiactorosServer; use Zend\Diactoros\Server as DiactorosServer;
use Zend\Stratigility\MiddlewarePipe; use Zend\Stratigility\MiddlewarePipe;
use Zend\Stratigility\NoopFinalHandler; use function Zend\Stratigility\middleware;
use function Zend\Stratigility\path; use function Zend\Stratigility\path;
class Server class Server implements Middleware, Handler
{ {
/** /**
* @param Site $site * @param Site $site
@ -46,33 +47,38 @@ class Server
public function listen() public function listen()
{ {
DiactorosServer::createServer( DiactorosServer::createServer(
$this, [$this, 'handle'],
$_SERVER, $_SERVER,
$_GET, $_GET,
$_POST, $_POST,
$_COOKIE, $_COOKIE,
$_FILES $_FILES
)->listen(new NoopFinalHandler()); )->listen();
} }
/** /**
* Use as PSR-7 middleware. * Use as PSR-15 middleware.
*
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @param callable $out
* @return ResponseInterface
*/ */
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $out) public function process(Request $request, Handler $handler): Response
{ {
$middleware = $this->getMiddleware($request->getUri()->getPath()); $middleware = $this->getMiddleware($request->getUri()->getPath());
return $middleware($request, $response, $out); return $middleware->process($request, $handler);
}
/**
* Use as PSR-15 request handler.
*/
public function handle(Request $request): Response
{
$middleware = $this->getMiddleware($request->getUri()->getPath());
return $middleware->handle($request);
} }
/** /**
* @param string $requestPath * @param string $requestPath
* @return MiddlewareInterface * @return MiddlewarePipe
*/ */
protected function getMiddleware($requestPath) protected function getMiddleware($requestPath)
{ {
@ -126,9 +132,9 @@ class Server
protected function getMaintenanceMiddleware(MiddlewarePipe $pipe) protected function getMaintenanceMiddleware(MiddlewarePipe $pipe)
{ {
$pipe->pipe(function () { $pipe->pipe(middleware(function () {
return new HtmlResponse(file_get_contents($this->getErrorDir().'/503.html', 503)); return new HtmlResponse(file_get_contents($this->getErrorDir().'/503.html', 503));
}); }));
// TODO: FOR API render JSON-API error document for HTTP 503 // TODO: FOR API render JSON-API error document for HTTP 503