ADR-005 - PSR-15 Middleware-Muster
ADR-005: PSR-15 Middleware-Muster für XOOPS 4.0
Abschnitt betitelt „ADR-005: PSR-15 Middleware-Muster für XOOPS 4.0“Übernehmen Sie PSR-15 HTTP Server Request Handler (Middleware) für verbesserte Request-Verarbeitungs-Pipeline.
Vorgeschlagen - Unter Bewertung für XOOPS 4.0 Release
Context
Abschnitt betitelt „Context“Aktueller Ansatz
Abschnitt betitelt „Aktueller Ansatz“XOOPS 2.5 verwendet einen monolithischen Request-Handling-Ansatz:
// Current: Sequential processingrequire_once 'mainfile.php';// → Kernel initialization// → User authentication// → Module loading// → Page rendering
// All in one flow, mixed concernsProbleme mit aktuellem Ansatz
Abschnitt betitelt „Probleme mit aktuellem Ansatz“- Gemischte Concerns - Authentifizierung, Protokollierung, Routing alle verflochten
- Schwer zu testen - Schwer, einzelne Request-Verarbeitungsschritte zu Unit-Testen
- Schwer zu erweitern - Module können nur über Preload/Events hooking
- Schlechte Separation - Request-Verarbeitungs-Logik verstreut im Codebase
- Nicht zusammensetzbar - Kann nicht einfach Verarbeitungsschritte verketten oder neu ordnen
Was ist PSR-15 Middleware?
Abschnitt betitelt „Was ist PSR-15 Middleware?“PSR-15 definiert eine Standard-Schnittstelle für HTTP Middleware:
<?phpinterface RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface;}
interface MiddlewareInterface { public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface;}Middleware-Chain:
Request ↓[Logger] → logs request ↓[Auth] → validates user session ↓[CORS] → checks cross-origin ↓[Router] → dispatches to handler ↓[Handler] → generates response ↓ResponseDecision
Abschnitt betitelt „Decision“Übernehmen Sie PSR-15 Middleware Stack für XOOPS 4.0
Abschnitt betitelt „Übernehmen Sie PSR-15 Middleware Stack für XOOPS 4.0“Implementieren Sie eine Middleware-basierte Request-Verarbeitungs-Pipeline nach PSR-15 Standard.
Architektur-Übersicht
Abschnitt betitelt „Architektur-Übersicht“graph TD subgraph "Request Processing Pipeline" A["HTTP Request<br/>(PSR-7 ServerRequest)"] B["Middleware Stack<br/>(PSR-15)"] C["Logger Middleware"] D["Session Middleware"] E["Auth Middleware"] F["CORS Middleware"] G["Router Middleware"] H["Handler<br/>(Controller/Action)"] I["Response<br/>(PSR-7 Response)"] end
A --> B B --> C C --> D D --> E E --> F F --> G G --> H H --> IKern-Middleware-Komponenten
Abschnitt betitelt „Kern-Middleware-Komponenten“1. Anwendungs-Middleware (Kern-Ebene)
Abschnitt betitelt „1. Anwendungs-Middleware (Kern-Ebene)“<?phpdeclare(strict_types=1);
namespace XoopsCore;
use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;use Psr\Http\Server\MiddlewareInterface;use Psr\Http\Server\RequestHandlerInterface;
class SessionMiddleware implements MiddlewareInterface{ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { // 1. Retrieve session (or start new) $sessionId = $request->getCookieParams()['PHPSESSID'] ?? null; $session = $this->sessionManager->load($sessionId);
// 2. Attach session to request $request = $request->withAttribute('session', $session);
// 3. Pass to next middleware $response = $handler->handle($request);
// 4. Set session cookie if needed if ($session->isModified()) { $response = $response->withAddedHeader( 'Set-Cookie', 'PHPSESSID=' . $session->getId() . '; HttpOnly; SameSite=Strict' ); }
return $response; }}2. Authentifizierungs-Middleware
Abschnitt betitelt „2. Authentifizierungs-Middleware“<?phpclass AuthMiddleware implements MiddlewareInterface{ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { // Get session from previous middleware $session = $request->getAttribute('session');
// Authenticate user from session $user = $this->authenticate($session);
// Attach user to request $request = $request->withAttribute('user', $user);
return $handler->handle($request); }
private function authenticate(?Session $session): User { if ($session && $session->has('uid')) { return $this->userRepository->findById($session->get('uid')); }
return new AnonymousUser(); }}3. Autorisierungs-Middleware
Abschnitt betitelt „3. Autorisierungs-Middleware“<?phpclass AuthorizationMiddleware implements MiddlewareInterface{ public function __construct(private AuthorizationChecker $checker) { }
public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { $user = $request->getAttribute('user'); $route = $request->getAttribute('route');
// Check if user has permission for this route if (!$this->checker->isGranted($user, $route)) { return new JsonResponse( ['error' => 'Unauthorized'], 403 ); }
return $handler->handle($request); }}4. Modul-Middleware
Abschnitt betitelt „4. Modul-Middleware“<?php// Modules can provide their own middlewareclass PublisherAccessMiddleware implements MiddlewareInterface{ public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { $user = $request->getAttribute('user');
// Module-specific access control if (!$user->hasPermission('publisher_view')) { return new HtmlResponse('Access denied', 403); }
return $handler->handle($request); }}Implementierungs-Beispiel
Abschnitt betitelt „Implementierungs-Beispiel“<?php// bootstrap.php - Application setup
use Psr\Http\Message\ServerRequestInterface;use Psr\Http\Server\RequestHandlerInterface;use Xoops\Core\Middleware\{ LoggerMiddleware, SessionMiddleware, AuthMiddleware, CorsMiddleware, ErrorHandlingMiddleware};
// Create middleware pipeline$middlewareStack = [ // 1. Error handling (outermost) new ErrorHandlingMiddleware(),
// 2. Logging new LoggerMiddleware($logger),
// 3. CORS handling new CorsMiddleware($corsConfig),
// 4. Session management new SessionMiddleware($sessionManager),
// 5. Authentication new AuthMiddleware($userRepository),
// 6. Authorization new AuthorizationMiddleware($authChecker),
// 7. Routing and dispatching new RoutingMiddleware($router),
// 8. Module middleware (dynamic) ...$this->loadModuleMiddleware(),];
// Process request through middleware stack$request = ServerRequestFactory::fromGlobals();$dispatcher = new MiddlewareDispatcher($middlewareStack);$response = $dispatcher->dispatch($request);
// Send responsehttp_response_code($response->getStatusCode());foreach ($response->getHeaders() as $name => $values) { foreach ($values as $value) { header("$name: $value", false); }}echo $response->getBody();Modul-Integration
Abschnitt betitelt „Modul-Integration“Module können Middleware bereitstellen:
<?php// Publisher module - xoops_version.php
$modversion['middleware'] = [ 'PublisherAccessMiddleware' => true, // Auto-load 'PublisherLogMiddleware' => true,];
// Or custom:$modversion['middleware_factory'] = function() { return [ new PublisherCacheMiddleware(), new PublisherPermissionMiddleware(), ];};Consequences
Abschnitt betitelt „Consequences“Positive Auswirkungen
Abschnitt betitelt „Positive Auswirkungen“- Separation of Concerns - Jede Middleware verwaltet eine Verantwortung
- Testbarkeit - Einfach, einzelne Middleware-Komponenten zu Unit-Testen
- Zusammensetzbarkeit - Middleware kann gemischt und neu geordnet werden
- Standards-Konformität - Verwendet PSR-15 und PSR-7 Standards
- Erweiterbarkeit - Module können einfach benutzerdefinierte Middleware hinzufügen
- Debugging - Klarer Request-Flow durch Pipeline
- Leistung - Kann spezifische Middleware-Schichten optimieren
- Interoperabilität - Kann Drittanbieter PSR-15 Middleware verwenden
Negative Auswirkungen
Abschnitt betitelt „Negative Auswirkungen“- Lernkurve - Entwickler müssen PSR-15 verstehen
- Leistungs-Overhead - Mehr Funktions-Aufrufe in Pipeline
- Komplexität - Mehr bewegliche Teile als monolithischer Ansatz
- Migrations-Aufwand - Erfordert Umgestaltung existierenden Codes
- Abhängigkeiten - Erfordert PSR-7 HTTP-Bibliothek
Risiken und Mitigationen
Abschnitt betitelt „Risiken und Mitigationen“| Risk | Severity | Mitigation |
|---|---|---|
| Complex middleware chains | Medium | Clear documentation, examples |
| Performance degradation | Medium | Benchmark, optimize hot paths |
| Developer misuse | Medium | Code review, best practices guide |
| Migration breaking changes | High | Deprecation period, helpers |
| Middleware ordering issues | Medium | Clear dependency graph |
Implementierungs-Plan
Abschnitt betitelt „Implementierungs-Plan“Phase 1: Foundation (Q2 2026)
Abschnitt betitelt „Phase 1: Foundation (Q2 2026)“- Implement PSR-7 HTTP message wrapper
- Create MiddlewareDispatcher
- Implement core middleware (session, auth)
- Update kernel to use middleware
Phase 2: Integration (Q3 2026)
Abschnitt betitelt „Phase 2: Integration (Q3 2026)“- Migrate existing functionality to middleware
- Add module middleware support
- Create middleware testing utilities
- Write comprehensive documentation
Phase 3: Migration (Q4 2026)
Abschnitt betitelt „Phase 3: Migration (Q4 2026)“- Provide compatibility layer for old code
- Help modules update to new middleware
- Performance optimization
- Security audit
Phase 4: Release (Q1 2027)
Abschnitt betitelt „Phase 4: Release (Q1 2027)“- XOOPS 4.0 release with middleware
- Deprecate old preload/hook system
- Community feedback and updates
Success-Kriterien
Abschnitt betitelt „Success-Kriterien“- All core functionality migrated to middleware
- 90%+ test coverage for middleware
- Documentation complete with examples
- Performance within 10% of previous version
- Modules successfully use new middleware system
- Community adoption rate >80%
Middleware Best Practices
Abschnitt betitelt „Middleware Best Practices“- Keep middleware focused (single responsibility)
- Use immutability (create new request/response)
- Handle errors gracefully
- Document dependencies
- Add type hints
- Write tests for middleware
- Use standard PSR-15 interfaces
- Don’t modify shared request/response objects
- Don’t access globals directly
- Don’t create dependencies on middleware order
- Don’t catch all exceptions
- Don’t mix business logic with middleware
- Don’t make middleware do too much
Beispiele
Abschnitt betitelt „Beispiele“Custom Middleware
Abschnitt betitelt „Custom Middleware“<?php// Example: Rate limiting middleware
use Psr\Http\Message\ResponseInterface;use Psr\Http\Message\ServerRequestInterface;use Psr\Http\Server\MiddlewareInterface;use Psr\Http\Server\RequestHandlerInterface;
class RateLimitMiddleware implements MiddlewareInterface{ public function __construct( private RateLimiter $limiter, private int $limit = 100, private int $window = 3600 ) { }
public function process( ServerRequestInterface $request, RequestHandlerInterface $handler ): ResponseInterface { $user = $request->getAttribute('user'); $identifier = $user->getId() ?? $request->getClientIp();
// Check rate limit $remaining = $this->limiter->check($identifier, $this->limit, $this->window);
if ($remaining < 0) { return new JsonResponse( ['error' => 'Rate limit exceeded'], 429 ); }
// Add rate limit headers $response = $handler->handle($request); return $response ->withAddedHeader('X-RateLimit-Limit', (string)$this->limit) ->withAddedHeader('X-RateLimit-Remaining', (string)$remaining); }}Related Decisions
Abschnitt betitelt „Related Decisions“- ADR-001: Modular Architecture - Foundation
- ADR-004: Security System - Uses middleware for auth
- ADR-006: Two-Factor Auth - Can be middleware
References
Abschnitt betitelt „References“PSR Standards
Abschnitt betitelt „PSR Standards“Middleware Frameworks
Abschnitt betitelt „Middleware Frameworks“- Slim Framework - Middleware examples
- Zend Expressive - PSR-15 framework
- Guzzle - HTTP client middleware
- RelayPHP - Middleware library
- PSR-15 Middleware - Collection of middlewares
Versions-Geschichte
Abschnitt betitelt „Versions-Geschichte“| Version | Date | Changes |
|---|---|---|
| 1.0.0 | 2024-01-28 | Initial proposal |
#xoops #adr #psr-15 #middleware #architecture #psr-7