Neos Flow Middleware Tutorial: PSR-15 verstehen und anwenden

Icon
Chris Wächter
02/2026
10 Lesedauer
Know How
Generated HTTP Application Flow
Icon
Chris Wächter
Fullstack Development
Meet the team
Zusammenfassung
Middlewares sind ein zentraler Bestandteil moderner Webanwendungen – auch in Neos Flow. In diesem Insight erfährst du in weniger als zehn Minuten, was Middlewares sind, warum sie im Rahmen des PSR-15-Standards wichtig sind und wie sie in Flow eingesetzt werden. Anhand einfacher Beispiele wird praxisnah gezeigt, wie Middlewares funktionieren und wo sie sinnvoll eingesetzt werden.

Was ist eine Middleware?

Im Kontext von PSR (PHP Standards Recommendation) und Web-Applikationen ist eine Middleware eine eigenständige Komponente, die einen HTTP Request entgegennimmt, ihn optional verändert oder verarbeitet und dann entweder selbst eine HTTP Response zurückgibt oder den Request an die nächste Middleware weiterleitet.

Warum ist es für Neos Flow wichtig?

Middlewares sind in Neos Flow wichtig, weil sie ein zentraler Bestandteil der PSR-basierten Architektur von Web-Applikationen sind. Mit ihnen kann man zum Beispiel prüfen, ob ein Benutzer authentifiziert und/oder autorisiert ist, bevor er eine sicherheitskritische Aktion wie das Ändern seines Passworts ausführt (SecurityEntryPointMiddleware). Ebenso lassen sich mit Middlewares Flashmessages (z. B. im Neos CMS Dashboard: „Datei Dummy.pdf wurde hinzugefügt.“) im Cookie speichern, um diese im Browser ausgeben lassen zu können (FlashMessageMiddleware).

Möglichkeiten, die sich durch Middlewares bieten:
 

Authentifizierung & Autorisierung

Prüfen, ob ein Benutzer eingeloggt ist oder die nötigen Rechte hat

 

Security & Schutzmaßnahmen

Zusätzliche Header setzen (Content-Security-Policy, X-Frame-Options, …)

 

Logging & Monitoring

Jede Anfrage oder bestimmte Events ins Log schreiben

Performance messen (z. B. Zeit vom Request bis zur Response)

Request- und Response-Manipulation

Query-Parameter oder Header ergänzen/ändern

Cookies setzen oder auswerten

Response-Body anpassen, bevor er zurückgeht
 

Wartungsmodus oder Feature-Flags

Statt der normalen Seite eine Wartungsseite zurückgeben

Bestimmte Features nur für Test-User aktivieren

So funktioniert eine Middleware in Neos Flow

Hier ist ein Sequenzdiagramm, wie Middlewares in Neos Flow einzuordnen sind:

Stark vereinfacht gesagt lässt sich das Diagramm so zusammenfassen: Der Browser sendet eine Anfrage an den Server. Dort übernimmt ein passender RequestHandler, der aus der Anfrage ein PSR-7-Request-Objekt erstellt. Dieses Objekt enthält alle relevanten Informationen der ursprünglichen HTTP-Anfrage und wird anschließend durch die nach PSR-15 implementierte Middleware-Kette geleitet.

 

PSR-7 definiert standardisierte PHP-Interfaces für HTTP-Nachrichten, also für Requests, Responses, Streams, URIs und hochgeladene Dateien. Dadurch gibt es eine gemeinsame, frameworkunabhängige Grundlage für die Arbeit mit HTTP-Objekten. Die Objekte sind unveränderlich aufgebaut, wodurch jede Veränderung eine neue Instanz erzeugt und somit ein konsistentes Verhalten garantiert wird.


PSR-15 baut auf diesen PSR-7-Interfaces auf und legt fest, wie Middlewares und Request-Handler im Server-Kontext aussehen. Eine Middleware erhält dabei ein PSR-7-Request-Objekt und entscheidet, ob sie selbst eine Response zurückgibt oder den Request an den nächsten Handler weiterleitet. Dadurch entsteht eine klar definierte und kompatible Middleware-Kette, die unabhängig vom verwendeten Framework funktioniert.

Wie implementiert man Middlewares in Neos Flow?

Wenn man eine eigene Middleware erstellen möchte, muss man das Psr\Http\Server\MiddlewareInterface implementieren. Dieses Interface definiert die process-Methode:

<?php

namespace Vendor\Package\Http;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

// A sample HTTP middleware that adds a custom header to the response
final class SomeMiddleware implements MiddlewareInterface
{
	public function process (ServerRequestInterface $request, RequestHandlerInterface $next): ResponseInterface {
		$response = $next->handle($request);
		return $response->withAddedHeader ('X-MyHeader', '123');
	}
}

 

Um die neue Middleware zu aktivieren, muss es in der Settings.yaml konfiguriert werden:

Neos:
  Flow:
    http:
      middlewares:
        'custom':
          position: 'before dispatch'
          middleware: 'Vendor\Package\Http\SomeMiddleware'

 

In der position-Option kann man angeben, an welcher Stelle der Middleware-Kette die neue Middleware verarbeitet werden soll. Mit ./flow middleware:list findet man alle aktive Middlewares:

$ ./flow middleware:list
Currently configured middlewares:
+----+---------------------+-----------------------------------------------------------------+
| #  | Name                | Class name                                                      |
+----+---------------------+-----------------------------------------------------------------+
| 1  | standardsCompliance | Neos\Flow\Http\Middleware\StandardsComplianceMiddleware         |
| 2  | trustedProxies      | Neos\Flow\Http\Middleware\TrustedProxiesMiddleware              |
| 3  | methodOverride      | Neos\Flow\Http\Middleware\MethodOverrideMiddleware              |
| 4  | session             | Neos\Flow\Http\Middleware\SessionMiddleware                     |
| 5  | ajaxWidget          | Neos\FluidAdaptor\Core\Widget\AjaxWidgetMiddleware              |
| 6  | detectSite          | Neos\Neos\FrontendRouting\SiteDetection\SiteDetectionMiddleware |
| 7  | routing             | Neos\Flow\Mvc\Routing\RoutingMiddleware                         |
| 8  | poweredByHeader     | Neos\Flow\Http\Middleware\PoweredByMiddleware                   |
| 9  | flashMessages       | Neos\Flow\Mvc\FlashMessage\FlashMessageMiddleware               |
| 10 | parseBody           | Neos\Flow\Http\Middleware\RequestBodyParsingMiddleware          |
| 11 | securityEntryPoint  | Neos\Flow\Http\Middleware\SecurityEntryPointMiddleware          |
| 12 | dispatch            | Neos\Flow\Mvc\DispatchMiddleware                                |
+----+---------------------+-----------------------------------------------------------------+

 

Die neue Middleware würde zwischen securityEntryPoint und dispatch aktiviert werden.

Eine Middleware-Implementierung in Neos Flow bietet verschiedene Möglichkeiten: Man kann die Middleware-Kette unterbrechen, Daten zwischen Middlewares austauschen, individuelle Optionen definieren und vieles mehr. Weitere Details findest du hier: https://flowframework.readthedocs.io/en/8.3/TheDefinitiveGuide/PartIII/Http.html#interrupting-the-chain

Praktische Beispiele

Logging Middleware für bestimmten Flow Kontext

<?php

namespace Vendor\Package\Http;

use Neos\Flow\Annotations as Flow;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Log\LoggerInterface;

// A middleware that logs all requests if they are in development context
class LoggingMiddleware implements MiddlewareInterface
{
	#[Flow\Inject] protected LoggerInterface $logger;

	#[Flow\InjectConfiguration(path: "core. context", package: "Neos.Flow", type: "Settings")]
	protected string $context = "Development";

	public function process (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
	{
		if ($this->context== "Development/Docker") {
			$this->logger->info("Incoming request: Method -> " . $request->getMethod() . "; Query -> " . $request->getUri()->getQuery());
		}

		return $response = $handler->handle($request);
	}
}


Wartungsmodus Middleware

<?php

namespace Vendor\Package\Http;

use Neos\Flow\Annotations as Flow;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Log\LoggerInterface;
use Vendor\Package\Http\MaintenanceResponse;

// A middleware that creates a maintenance response if in maintenance mode and not permitted user
class MaintenanceMiddleware implements MiddlewareInterface
{
	#[Flow\InjectConfiguration(path: "core.maintenanceActive", package: "Vendor.Package", type: "Settings")]
	protected bool $isMaintenanceActive = false;

	public function process (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
	{
		$clientIp = $request->getServerParams()['REMOTE_ADDR'] ?? '';

		if (!$this->isMaintenanceActive || $clientIp === "123.123.123.123") {
			return $handler->handle($request);
		}

		return new MaintenanceResponse();
	}
}


Weiterführende Links

Wir haben dir spannende
Geschichten zu erzählen.