İçeriğe geç

ADR-005 - PSR-15 Ara Katman Kalıbı

ADR-005: PSR-15 XOOPS 4.0 için Ara Yazılım Kalıbı

Section titled “ADR-005: PSR-15 XOOPS 4.0 için Ara Yazılım Kalıbı”

Gelişmiş istek işleme hattı için PSR-15 HTTP sunucu istek işleyicilerini (ara yazılım) benimseyin.


Önerilen - XOOPS 4.0 sürümü için değerlendirme aşamasında


XOOPS 2.5, monolitik bir istek işleme yaklaşımı kullanır:

// Current: Sequential processing
require_once 'mainfile.php';
// → Kernel initialization
// → User authentication
// → Module loading
// → Page rendering
// All in one flow, mixed concerns
  1. Karışık Endişeler - Kimlik doğrulama, günlük kaydı ve yönlendirme hepsi iç içe geçmiş
  2. Test Edilmesi Zor - Bireysel istek işleme adımlarını birim test etmek zor
  3. Uzatılması Zor - modules yalnızca preload/events aracılığıyla bağlanabilir
  4. Kötü Ayırma - İstek işleme mantığı kod tabanına dağılmış durumda
  5. Biçimlendirilemez - İşleme adımları kolaylıkla zincirlenemez veya yeniden sıralanamaz

PSR-15, HTTP ara yazılımı için standart bir arayüz tanımlar:

<?php
interface RequestHandlerInterface {
public function handle(ServerRequestInterface $request): ResponseInterface;
}
interface MiddlewareInterface {
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface;
}

Ara katman yazılımı zinciri:

Request
[Logger] → logs request
[Auth] → validates user session
[CORS] → checks cross-origin
[Router] → dispatches to handler
[Handler] → generates response
Response

XOOPS 4.0 için PSR-15 Ara Yazılım Yığınını benimseyin

Section titled “XOOPS 4.0 için PSR-15 Ara Yazılım Yığınını benimseyin”

PSR-15 standardına uygun olarak ara yazılım tabanlı bir istek işleme hattı uygulayın.

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 --> I
<?php
declare(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;
}
}
<?php
class 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();
}
}
<?php
class 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);
}
}
<?php
// Modules can provide their own middleware
class 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);
}
}
<?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 response
http_response_code($response->getStatusCode());
foreach ($response->getHeaders() as $name => $values) {
foreach ($values as $value) {
header("$name: $value", false);
}
}
echo $response->getBody();

modules ara yazılım sağlayabilir:

<?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(),
];
};

  1. Endişelerin Ayrılması - Her ara yazılım tek bir sorumluluğu üstlenir
  2. Test Edilebilirlik - Bireysel ara yazılım bileşenlerinin birim testine tabi tutulması kolaydır
  3. Şekillendirilebilirlik - Ara yazılımlar karıştırılabilir ve yeniden sıralanabilir
  4. Standartlarla Uyumlu - PSR-15 ve PSR-7 standartlarını kullanır
  5. Genişletilebilirlik - modules kolayca özel ara yazılım ekleyebilir
  6. Hata ayıklama - Ardışık düzen boyunca istek akışını temizleyin
  7. Performans - Belirli ara yazılım katmanlarını optimize edebilir
  8. Birlikte çalışabilirlik - Üçüncü taraf PSR-15 ara yazılımını kullanabilir
  1. Öğrenim Eğrisi - Geliştiricilerin PSR-15’i anlaması gerekir
  2. Performans Ek Yükü - İşlem hattında daha fazla işlev çağrısı
  3. Karmaşıklık - Monolitik yaklaşıma göre daha fazla hareketli parça
  4. Geçiş Çabası - Mevcut kodun yeniden düzenlenmesini gerektirir
  5. Bağımlılıklar - PSR-7 HTTP kitaplığı gerektirir
RiskŞiddetAzaltma
Karmaşık ara yazılım zincirleriOrtaAçık belgeler, örnekler
Performans düşüşüOrtaSıcak yolları kıyaslayın, optimize edin
Geliştiricinin kötüye kullanımıOrtaKod incelemesi, en iyi uygulamalar kılavuzu
Geçişi bozan değişikliklerYüksekKullanımdan kaldırma süresi, yardımcılar
Ara yazılım sıralama sorunlarıOrtaBağımlılık grafiğini temizle

  • PSR-7 HTTP mesaj sarmalayıcıyı uygulayın
  • MiddlewareDispatcher’ı oluştur
  • Core ara katman yazılımını uygulayın (oturum, kimlik doğrulama)
  • Ara yazılımı kullanmak için çekirdeği güncelleyin
  • Mevcut işlevselliği ara yazılıma taşıyın
  • module ara yazılım desteği ekleyin
  • Ara katman yazılımı test yardımcı programları oluşturun
  • Kapsamlı belgeler yazın
  • Eski kod için uyumluluk katmanı sağlayın
  • Yardım modüllerinin yeni ara yazılıma güncellenmesi
  • Performans optimizasyonu
  • Güvenlik denetimi
  • XOOPS 4.0 ara katman yazılımı sürümü
  • Eski preload/hook sistemini kullanımdan kaldırın
  • Topluluk geri bildirimleri ve güncellemeler

  • Tüm temel işlevler ara yazılıma taşındı
  • Ara katman yazılımı için %90+ test kapsamı
  • Örneklerle dolu belgeler
  • Önceki sürüme göre %10’luk performans
  • modules yeni ara yazılım sistemini başarıyla kullanıyor
  • Topluluğun benimseme oranı >%80

  • Ara katman yazılımını odaklı tutun (tek sorumluluk)
  • Değişmezliği kullanın (yeni request/response) oluşturun)
  • Hataları incelikle ele alın
  • Belge bağımlılıkları
  • Yazım ipuçları ekleyin
  • Ara yazılım için testler yazın
  • Standart PSR-15 arayüzlerini kullanın
  • Paylaşılan request/response nesnelerini değiştirmeyin
  • Globallere doğrudan erişmeyin
  • Ara yazılım sırasına bağımlılıklar yaratmayın
  • Tüm istisnaları yakalamayın
  • İş mantığını ara yazılımla karıştırmayın
  • Ara yazılımların çok fazla iş yapmasını sağlamayın

<?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);
}
}

  • ADR-001: Modüler Mimari - Temel
  • ADR-004: Güvenlik Sistemi - Kimlik doğrulama için ara yazılım kullanır
  • ADR-006: İki Faktörlü Kimlik Doğrulama - Ara yazılım olabilir


SürümTarihDeğişiklikler
1.0.02024-01-28İlk teklif

#xoops #adr #psr-15 #middleware #architecture #psr-7