Skip to content

ADR-005 - PSR-15 Vzorec vmesne programske opreme

ADR-005: PSR-15 Vzorec vmesne programske opreme za XOOPS 4.0

Section titled “ADR-005: PSR-15 Vzorec vmesne programske opreme za XOOPS 4.0”

Sprejmite PSR-15 HTTP strežniške obdelovalce zahtev (vmesna programska oprema) za izboljšan cevovod za obdelavo zahtev.


Predlagano - V ocenjevanju za izdajo XOOPS 4.0


XOOPS 2.5 uporablja monoliten pristop obravnavanja zahtev:

// Current: Sequential processing
require_once 'mainfile.php';
// → Kernel initialization
// → User authentication
// → Module loading
// → Page rendering
// All in one flow, mixed concerns
  1. Mešani pomisleki – avtentikacija, beleženje, usmerjanje so prepleteni
  2. Težko za testiranje - Težko za enotno testiranje posameznih korakov obdelave zahtev
  3. Težko razširiti - Moduli se lahko priklopijo samo prek preload/events
  4. Slabo ločevanje – logika obdelave zahtev je razpršena po kodni bazi
  5. Ni mogoče sestaviti – korakov obdelave ni mogoče zlahka verižiti ali preurediti

PSR-15 definira standardni vmesnik za HTTP vmesno programsko opremo:

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

Veriga vmesne programske opreme:

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

Sprejmite sklad vmesne programske opreme PSR-15 za XOOPS 4.0

Section titled “Sprejmite sklad vmesne programske opreme PSR-15 za XOOPS 4.0”

Izvedite cevovod za obdelavo zahtev, ki temelji na vmesni programski opremi, po standardu PSR-15.

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

Osrednje komponente vmesne programske opreme

Section titled “Osrednje komponente vmesne programske opreme”

1. Vmesna programska oprema aplikacije (jedrna plast)

Section titled “1. Vmesna programska oprema aplikacije (jedrna plast)”
<?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;
}
}

2. Vmesna programska oprema za preverjanje pristnosti

Section titled “2. Vmesna programska oprema za preverjanje pristnosti”
<?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();
}
}

3. Vmesna programska oprema za avtorizacijo

Section titled “3. Vmesna programska oprema za avtorizacijo”
<?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();

Moduli lahko zagotovijo vmesno programsko opremo:

<?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. Ločitev skrbi - Vsaka vmesna programska oprema ima eno odgovornost
  2. Preizkušljivost - Preprosto enotno testiranje posameznih komponent vmesne programske opreme
  3. Zložljivost - Vmesno programsko opremo je mogoče mešati in preurejati
  4. Skladno s standardi - uporablja standarda PSR-15 in PSR-7
  5. Razširljivost - Moduli lahko enostavno dodajo vmesno programsko opremo po meri
  6. Odpravljanje napak - Počisti tok zahtev skozi cevovod
  7. Zmogljivost – lahko optimizira specifične plasti vmesne programske opreme
  8. Interoperabilnost - lahko uporablja vmesno programsko opremo PSR-15 tretjih oseb
  1. Krivulja učenja – razvijalci morajo razumeti PSR-15
  2. Performance Overhead – več funkcijskih klicev v cevovodu
  3. Kompleksnost – Več gibljivih delov kot monoliten pristop
  4. Prizadevanje za selitev - zahteva preoblikovanje obstoječe kode
  5. Odvisnosti - Zahteva knjižnico PSR-7 HTTP
TveganjeResnostUblažitev
Kompleksne vmesne verigeSrednjeJasna dokumentacija, primeri
Poslabšanje zmogljivostiSrednjePrimerjalno merilo, optimizirajte vroče poti
Zloraba razvijalcaSrednjePregled kode, vodnik po najboljših praksah
Spremembe, ki prekinjajo migracijoVisokObdobje amortizacije, pomočniki
Težave z naročanjem vmesne programske opremeSrednjePočisti graf odvisnosti
  • Implementiraj PSR-7 HTTP ovoj sporočila
  • Ustvarite MiddlewareDispatcher
  • Izvedba jedrne vmesne programske opreme (seja, avtorizacija)
  • Posodobite jedro za uporabo vmesne programske opreme
  • Preselitev obstoječe funkcionalnosti na vmesno programsko opremo
  • Dodajte podporo za vmesno programsko opremo modula
  • Ustvarite pripomočke za testiranje vmesne programske opreme
  • Napišite obsežno dokumentacijo
  • Zagotavlja združljivostno plast za staro kodo
  • Moduli pomoči se posodobijo na novo vmesno programsko opremo
  • Optimizacija zmogljivosti
  • Varnostna revizija
  • XOOPS Izdaja 4.0 z vmesno programsko opremo
  • Opusti stari sistem preload/hook
  • Povratne informacije in posodobitve skupnosti

  • Vse osnovne funkcije so se preselile v vmesno programsko opremo
  • 90 %+ testna pokritost za vmesno programsko opremo
  • Dokumentacija s primeri
  • Zmogljivost znotraj 10 % prejšnje različice
  • Moduli uspešno uporabljajo nov sistem vmesne programske opreme
  • Stopnja posvojitve v skupnosti >80 %

Najboljše prakse vmesne programske opreme

Section titled “Najboljše prakse vmesne programske opreme”
  • Osredotočite se na vmesno programsko opremo (ena odgovornost)

  • Uporabi nespremenljivost (ustvari nov request/response)

  • Napake obravnavajte elegantno

  • Odvisnosti dokumentov

  • Dodajte tipske namige

  • Napišite teste za vmesno programsko opremo

  • Uporabite standardne vmesnike PSR-15### Ne

  • Ne spreminjajte skupnih request/response objektov

  • Ne dostopajte neposredno do globalov

  • Ne ustvarjajte odvisnosti od vrstnega reda vmesne programske opreme

  • Ne ujemite vseh izjem

  • Ne mešajte poslovne logike z vmesno programsko opremo

  • Naj vmesna programska oprema ne naredi preveč


<?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: Modularna arhitektura - temelj
  • ADR-004: Varnostni sistem - uporablja vmesno programsko opremo za avt.
  • ADR-006: dvofaktorska avtorizacija - lahko vmesna programska oprema


RazličicaDatumSpremembe
1.0.02024-01-28Začetni predlog

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