Middleware
Overview
Middleware intercepts HTTP requests before they reach controllers and responses before they're sent to clients.
text
Request
↓
Middleware 1 (before)
↓
Middleware 2 (before)
↓
Controller
↓
Middleware 2 (after)
↓
Middleware 1 (after)
↓
ResponseGlobal Middleware
Applied to all routes:
php
use Nexphant\App;
use Nexphant\Server\Middleware\{Cors, Logger, Security};
$app = App::create();
$app->middleware(Cors::class);
$app->middleware(Logger::class);
$app->middleware(Security::class);Route Middleware
Applied to specific routes:
php
$app->get('/admin', function () {
return ['admin' => 'panel'];
})->middleware('auth');Middleware Aliases
Define reusable aliases:
php
$app->middlewareAlias([
'auth' => \Nexphant\Server\Middleware\AuthMiddleware::class,
'jwt' => \Nexphant\Server\Middleware\JwtMiddleware::class,
'csrf' => \Nexphant\Server\Middleware\CsrfMiddleware::class,
'throttle' => \Nexphant\Server\Middleware\RateLimit::class,
]);
// Usage
$app->get('/api/data', fn() => [])->middleware('auth');Route Groups
php
$app->group(['middleware' => ['auth', 'csrf']], function ($group) {
$group->get('/profile', fn() => ['user' => auth()->user()]);
$group->post('/update', fn(Request $req) => ['updated' => true]);
});Built-in Middleware
CORS
Cross-Origin Resource Sharing:
php
use Nexphant\Server\Middleware\Cors;
$cors = new Cors([
'origins' => ['https://example.com'],
'methods' => ['GET', 'POST', 'PUT', 'DELETE'],
'headers' => ['Content-Type', 'Authorization'],
'credentials' => true,
'max_age' => 3600,
]);
$app->middleware($cors);Allow all:
php
$cors = new Cors([
'origins' => ['*'],
'methods' => ['*'],
'headers' => ['*'],
]);Rate Limiting
php
use Nexphant\Server\Middleware\RateLimit;
$rateLimit = new RateLimit(
attempts: 60, // requests
per: 1, // minutes
);
$app->get('/api/data', fn() => [])
->middleware($rateLimit);Attribute-based:
php
use Nexphant\Server\Attributes\Throttle;
class ApiController
{
#[Throttle(attempts: 60, per: 1)]
public function index()
{
return ['data' => []];
}
}Security Headers
php
use Nexphant\Server\Middleware\Security;
$security = new Security([
'csp' => "default-src 'self'",
'xss_protection' => true,
'content_type_nosniff' => true,
'frame_options' => 'SAMEORIGIN',
'hsts' => [
'enabled' => true,
'max_age' => 31536000,
'include_subdomains' => true,
],
]);
$app->middleware($security);Compression
php
use Nexphant\Server\Middleware\Compress;
$compress = new Compress([
'threshold' => 1024, // Compress responses > 1KB
'level' => 6, // Compression level (1-9)
]);
$app->middleware($compress);Request Timeout
php
use Nexphant\Server\Middleware\Timeout;
$timeout = new Timeout(seconds: 30);
$app->middleware($timeout);Logger
php
use Nexphant\Server\Middleware\Logger;
$logger = new Logger([
'format' => ':method :url :status :response_time ms',
'skip' => ['/health', '/metrics'],
]);
$app->middleware($logger);Session
php
use Nexphant\Server\Middleware\SessionMiddleware;
$app->middleware(SessionMiddleware::class);CSRF Protection
php
use Nexphant\Server\Middleware\CsrfMiddleware;
$app->middleware(SessionMiddleware::class);
$app->middleware(CsrfMiddleware::class);Authentication
php
use Nexphant\Server\Middleware\AuthMiddleware;
$app->middlewareAlias(['auth' => AuthMiddleware::class]);
$app->get('/profile', fn() => [])->middleware('auth');JWT
php
use Nexphant\Server\Middleware\JwtMiddleware;
$jwt = new JwtMiddleware([
'secret' => env('JWT_SECRET'),
'algorithm' => 'HS256',
]);
$app->middlewareAlias(['jwt' => $jwt]);
$app->get('/api/protected', fn() => [])->middleware('jwt');Cookie
php
use Nexphant\Server\Middleware\CookieMiddleware;
$app->middleware(CookieMiddleware::class);Trusted Proxy
php
use Nexphant\Server\Middleware\TrustedProxyMiddleware;
$proxy = new TrustedProxyMiddleware([
'proxies' => ['10.0.0.0/8', '172.16.0.0/12'],
'headers' => [
'forwarded' => 'X-Forwarded-For',
'proto' => 'X-Forwarded-Proto',
'host' => 'X-Forwarded-Host',
'port' => 'X-Forwarded-Port',
],
]);
$app->middleware($proxy);Content Security Policy
php
use Nexphant\Server\Middleware\CspMiddleware;
$csp = new CspMiddleware([
'default-src' => ["'self'"],
'script-src' => ["'self'", "'unsafe-inline'", 'https://cdn.example.com'],
'style-src' => ["'self'", "'unsafe-inline'"],
'img-src' => ["'self'", 'data:', 'https:'],
'font-src' => ["'self'", 'data:'],
'report-uri' => '/csp-report',
]);
$app->middleware($csp);Metrics
php
use Nexphant\Server\Middleware\MetricsMiddleware;
$metrics = new MetricsMiddleware();
$app->middleware($metrics);Custom Middleware
Basic Structure
php
use Nexphant\Server\Middleware\MiddlewareInterface;
class CustomMiddleware implements MiddlewareInterface
{
public function handle($request, $next)
{
// Before controller
$response = $next($request);
// After controller
return $response;
}
}Modify Request
php
class AddHeaderMiddleware implements MiddlewareInterface
{
public function handle($request, $next)
{
$request = $request->withHeader('X-Custom', 'value');
return $next($request);
}
}Modify Response
php
class AddResponseHeaderMiddleware implements MiddlewareInterface
{
public function handle($request, $next)
{
$response = $next($request);
return $response->withHeader('X-Response-Time', '100ms');
}
}Early Return
php
class MaintenanceModeMiddleware implements MiddlewareInterface
{
public function handle($request, $next)
{
if (file_exists(storage_path('maintenance.lock'))) {
return Response::json([
'error' => 'Site under maintenance',
])->withStatus(503);
}
return $next($request);
}
}With Configuration
php
class IpWhitelistMiddleware implements MiddlewareInterface
{
private array $whitelist;
public function __construct(array $whitelist)
{
$this->whitelist = $whitelist;
}
public function handle($request, $next)
{
$ip = $request->ip();
if (!in_array($ip, $this->whitelist)) {
return Response::json(['error' => 'Forbidden'])
->withStatus(403);
}
return $next($request);
}
}
// Usage
$app->middleware(new IpWhitelistMiddleware([
'192.168.1.1',
'10.0.0.1',
]));Complete Examples
API with Auth + Rate Limiting
php
use Nexphant\App;
use Nexphant\Server\Middleware\{JwtMiddleware, RateLimit, Cors};
$app = App::create();
// Global
$app->middleware(new Cors(['origins' => ['*']]));
// Aliases
$app->middlewareAlias([
'jwt' => new JwtMiddleware(['secret' => env('JWT_SECRET')]),
'throttle' => new RateLimit(60, 1),
]);
// Public routes
$app->post('/auth/login', fn(Request $req) => ['token' => 'jwt...']);
// Protected routes
$app->group(['prefix' => '/api', 'middleware' => ['jwt', 'throttle']], function ($group) {
$group->get('/users', fn() => User::query()->get());
$group->post('/users', fn(Request $req) => ['created' => true]);
});
$app->listen(port: 8080);Admin Panel
php
$app->middlewareAlias([
'auth' => AuthMiddleware::class,
'admin' => AdminMiddleware::class,
'csrf' => CsrfMiddleware::class,
]);
$app->group(['prefix' => '/admin', 'middleware' => ['auth', 'admin', 'csrf']], function ($group) {
$group->get('/dashboard', fn() => view('admin.dashboard'));
$group->get('/users', fn() => view('admin.users'));
$group->post('/users', fn(Request $req) => ['created' => true]);
});Multi-tenant Application
php
class TenantMiddleware implements MiddlewareInterface
{
public function handle($request, $next)
{
$subdomain = $request->subdomain();
$tenant = Tenant::query()
->where('subdomain', $subdomain)
->first();
if (!$tenant) {
return Response::json(['error' => 'Tenant not found'])
->withStatus(404);
}
// Store tenant in context
Context::set('tenant', $tenant);
// Switch database connection
DB::setConnection($tenant->database);
return $next($request);
}
}
$app->middleware(new TenantMiddleware());Middleware Order
Order matters:
php
// Correct order
$app->middleware(TrustedProxyMiddleware::class); // 1. Trust proxy
$app->middleware(Cors::class); // 2. CORS
$app->middleware(SessionMiddleware::class); // 3. Session
$app->middleware(CsrfMiddleware::class); // 4. CSRF
$app->middleware(AuthMiddleware::class); // 5. Auth
$app->middleware(RateLimit::class); // 6. Rate limitConditional Middleware
php
class ConditionalMiddleware implements MiddlewareInterface
{
public function handle($request, $next)
{
if ($request->is('/api/*')) {
// API logic
} else {
// Web logic
}
return $next($request);
}
}Best Practices
- Order middleware correctly (proxy → cors → session → csrf → auth)
- Use global middleware for cross-cutting concerns
- Use route middleware for specific routes
- Keep middleware focused on single responsibility
- Return early when possible
- Use aliases for reusability
- Configure middleware via constructor
- Test middleware independently
