--- /dev/null
+<?php
+
+namespace wcf\http;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+/**
+ * Represents a middleware pipeline that sends the ServerRequestInterface
+ * through all MiddlewareInterfaces in the order they were given. The last
+ * MiddlewareInterface will be connected to the RequestHandlerInterface.
+ *
+ * @author Tim Duesterhus
+ * @copyright 2001-2022 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Http
+ * @since 5.6
+ */
+final class Pipeline implements MiddlewareInterface
+{
+ /**
+ * @var MiddlewareInterface[]
+ */
+ private array $middlewares;
+
+ /**
+ * @param MiddlewareInterface[] $middlewares
+ */
+ public function __construct(array $middlewares)
+ {
+ $this->middlewares = $middlewares;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+ {
+ foreach (\array_reverse($this->middlewares) as $middleware) {
+ $handler = new RequestHandlerMiddleware($middleware, $handler);
+ }
+
+ return $handler->handle($request);
+ }
+}
--- /dev/null
+<?php
+
+namespace wcf\http;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+/**
+ * Connects the given RequestHandlerInterface to the given MiddlewareInterface to transform the
+ * MiddlewareInterface into a RequestHandlerInterface.
+ *
+ * @author Tim Duesterhus
+ * @copyright 2001-2022 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Http
+ * @since 5.6
+ */
+final class RequestHandlerMiddleware implements RequestHandlerInterface
+{
+ private RequestHandlerInterface $handler;
+
+ private MiddlewareInterface $middleware;
+
+ public function __construct(MiddlewareInterface $middleware, RequestHandlerInterface $handler)
+ {
+ $this->middleware = $middleware;
+ $this->handler = $handler;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ return $this->middleware->process($request, $this->handler);
+ }
+}