Osumi Framework
es en eu v9.9.1 GitHub

Middlewareak

Osumi Framework-eko Middlewareak HTTP eskaera baten bizi-zikloan parte hartzen duten klase berrerabilgarriak dira.

Hiru fasetan exekuta daitezke:

Ohiko erabilerak hauek dira:


1. Middleware baten egitura

Aplikazioko Middlewareak normalean hemen gordetzen dira:

src/Middleware/

Middleware klase batek handle() metodo estatiko publiko bat izan behar du:

<?php

declare(strict_types=1);

namespace Osumi\OsumiFramework\App\Middleware;

final class ExampleMiddleware {
	/**
	 * Handle a middleware execution phase.
	 *
	 * @param string $phase Current middleware phase.
	 * @param array<string, mixed> $data Current middleware pipeline data.
	 *
	 * @return array<string, mixed> Middleware result.
	 */
	public static function handle(
		string $phase,
		array $data
	): array {
		return [];
	}
}

Middleware klase bera fase batean edo gehiagotan erregistratu daiteke.

$phase argumentuak une horretan exekutatzen ari den fasea adierazten du.

$data argumentuak eskaeraren informazioa eta Middleware pipeline-aren uneko egoera biltzen ditu.


2. Middleware faseak

Osumi Framework-ek hiru fase definitzen ditu OMiddleware bidez:

OMiddleware::PHASE_BEFORE
OMiddleware::PHASE_AFTER_RENDER
OMiddleware::PHASE_AFTER_RESPONSE

Exekuzio-ordena hau da:

Bideratzea
↓
before
↓
Osagaia
↓
afterRender
↓
Layout-a
↓
afterResponse
↓
HTTP erantzuna

before

Osagaia instantziatu aurretik exekutatzen da.

Ohiko erabilerak:

before Middleware batek pipeline normala geldiaraz dezake osagaia exekutatu aurretik.

afterRender

Osagaiaren txantiloia errendatu ondoren eta layout-a aplikatu aurretik exekutatzen da.

Ohiko erabilerak:

afterRender Middleware batek exekuzioa gelditzen badu, layout-a ez da errendatzen.

afterResponse

Erantzunaren azken gorputza sortu ondoren exekutatzen da.

Ohiko erabilerak:

afterResponse ere exekutatzen da aurreko before edo afterRender Middleware batek pipeline normala geldiarazi badu. Kasu horretan Middleware errorearen egoera ikuska dezake.

afterResponse Middleware batek berak exekuzioa gelditzen badu, fase horretako gainerako Middlewareak ez dira exekutatzen eta bere errore-erantzuna zuzenean bidaltzen da.


3. Middleware baten emaitza

handle() metodoak beti array bat itzuli behar du.

Array huts batek esan nahi du Middlewareak ez duela pipeline-a aldatzen:

return [];

Middleware batek honako gako hauek itzul ditzake.

context

Ondorengo Middlewareek, ORequest-ek edo DTOek erabil ditzaketen datuak argitaratzen ditu:

return [
	'context' => [
		'id' => 42,
		'role' => 'admin'
	]
];

Testuingurua Middlewarearen izen publikoarekin gordetzen da.

Adibidez:

LoginMiddleware

honela azaltzen da:

Login

body

Errendatutako gorputz bat ordezkatzen du:

return [
	'body' => 'Modified response'
];

Eragina fasearen araberakoa da:

headers

HTTP erantzun-goiburuak gehitzen edo ordezkatzen ditu:

return [
	'headers' => [
		'X-Request-Id' => 'abc123'
	]
];

Goiburuen izenak maiuskulak eta minuskulak bereizi gabe kudeatzen dira.

status_code

HTTP egoera-kodea aldatzen du:

return [
	'status_code' => 201
];

Baliozko egoera-kodeak 100 eta 599 artean daude.

stop

Uneko Middleware pipeline-a geldiarazten du:

return [
	'stop' => true,
	'status_code' => 403,
	'message' => 'Forbidden'
];

stop true denean:

Ez badira adierazten:


4. Autentifikazio Middleware baten adibidea

<?php

declare(strict_types=1);

namespace Osumi\OsumiFramework\App\Middleware;

use Osumi\OsumiFramework\Core\OMiddleware;

final class LoginMiddleware {
	/**
	 * Validate the request and publish authenticated user context.
	 *
	 * @param string $phase Current middleware phase.
	 * @param array<string, mixed> $data Current middleware pipeline data.
	 *
	 * @return array<string, mixed> Middleware result.
	 */
	public static function handle(
		string $phase,
		array $data
	): array {
		if ($phase !== OMiddleware::PHASE_BEFORE) {
			return [];
		}

		$headers = $data['headers'];

		if (
			!is_array($headers) ||
			!array_key_exists('Authorization', $headers)
		) {
			return [
				'stop' => true,
				'status_code' => 401,
				'message' => 'Unauthorized'
			];
		}

		return [
			'context' => [
				'id' => 42,
				'role' => 'admin'
			]
		];
	}
}

Middlewareak:

[
	'id' => 42,
	'role' => 'admin'
]

balioak Login testuinguru gisa argitaratzen ditu.


5. Middleware globalak

Proiektu osoko Middlewareak hemen konfiguratzen dira:

src/Middleware/Middlewares.php

Adibidez:

<?php

declare(strict_types=1);

namespace Osumi\OsumiFramework\App\Middleware;

use Osumi\OsumiFramework\Core\OMiddleware;

OMiddleware::setGlobal([
	OMiddleware::PHASE_BEFORE => [
		RequestMiddleware::class
	],
	OMiddleware::PHASE_AFTER_RENDER => [],
	OMiddleware::PHASE_AFTER_RESPONSE => [
		AuditMiddleware::class
	]
]);

Middleware globalak bat datorren ibilbide guztiei aplikatzen zaizkie.


6. Ibilbideko Middlewareak

Middlewareak zuzenean ibilbide bati eslei dakizkioke:

ORoute::get(
	'/profile',
	ProfileComponent::class,
	[
		OMiddleware::PHASE_BEFORE => [
			LoginMiddleware::class
		],
		OMiddleware::PHASE_AFTER_RESPONSE => [
			AuditMiddleware::class
		]
	]
);

7. Taldeko Middlewareak

prefix(), layout() eta group() metodoek Middleware definizioak jaso ditzakete.

Adibidez:

ORoute::prefix(
	'/api',
	static function (): void {
		ORoute::get(
			'/profile',
			ProfileComponent::class
		);
	},
	[
		OMiddleware::PHASE_BEFORE => [
			ApiMiddleware::class
		]
	]
);

Habiaratutako taldeek beren Middlewareak metatzen dituzte.

Fase bakoitzean exekuzio-ordena hau da:

global
↓
kanpoko taldea
↓
barneko taldea
↓
ibilbidea

Ordena hori modu independentean mantentzen da Middleware fase bakoitzean.


8. Middleware testuingurua ORequest-etik atzitzea

Middleware baten testuinguru osoa lortzeko:

$login = $req->getMiddleware(
	'Login'
);

Balio bakar bat lortzeko:

$id = $req->getMiddlewareValue(
	'Login',
	'id'
);

Ez dagoen Middleware testuinguru batek array hutsa itzultzen du.

Ez dagoen testuinguru-balio batek null itzultzen du.


9. Middleware testuingurua DTOetan erabiltzea

DTO eremuek Middleware testuingurua datu-iturburu esplizitu gisa erabil dezakete:

#[ODTOField(
	required: true,
	middleware: 'Login',
	middlewareProperty: 'id'
)]
public ?int $idUser = null;

middleware eta middlewareProperty beti batera definitu behar dira.

Balioa Middlewarearen testuingurutik lortzen da, bezeroak bidalitako datuetatik hartu beharrean.

Horri esker, bezero batek ezin ditu gainidatzi autentifikatutako erabiltzailearen IDa bezalako konfiantzazko balioak.


10. Errore-egoera afterResponse fasean

before edo afterRender faseek pipeline-a gelditzen dutenean, afterResponse exekutatzen jarraitzen da.

Bere $data array-ak honako balio hauek ditu:

$data['is_error']
$data['error_phase']
$data['error_status_code']
$data['error_message']

Horri esker, auditoria edo logging Middleware batek eskaera nola amaitu den ikuska dezake.

Adibidez:

if (
	$phase === OMiddleware::PHASE_AFTER_RESPONSE &&
	$data['is_error'] === true
) {
	// Middleware errorea erregistratu.
}

11. Praktika onak


12. Eskaeraren fluxu osoa

Bezeroaren eskaera
↓
Bideratzea
↓
before Middleware globalak
↓
Taldeetako before Middlewareak
↓
Ibilbideko before Middlewareak
↓
Osagaia / DTO / ORequest
↓
Osagaiaren errendatzea
↓
afterRender Middlewareak
↓
Layout-aren errendatzea
↓
afterResponse Middlewareak
↓
HTTP erantzuna

before edo afterRender faseko stop batek gainerako prozesamendu normala saihesten du, baina afterResponse fasera iristen da hala ere.

afterResponse barruko stop batek azken fase hori amaitzen du eta bere errore-erantzuna zuzenean bidaltzen du.