Skip to content

Middleware

Introduction

Middleware filters HTTP requests entering your application. Common uses:

  • Authentication
  • Logging
  • CORS headers
  • Rate limiting

How Middleware Works

Middleware wraps around your application like layers of an onion:

Request → Middleware A → Middleware B → Controller → Response
              ↓               ↓             ↓
         (before)        (before)      (handle)
              ↑               ↑             │
         (after)         (after)    ←───────┘

Each middleware can:

  • Modify the request before passing it on
  • Modify the response after receiving it
  • Short-circuit and return early

Creating Middleware

Implement MiddlewareInterface:

php
<?php

namespace App\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class LoggingMiddleware implements MiddlewareInterface
{
    public function process(
        ServerRequestInterface $request,
        RequestHandlerInterface $handler
    ): ResponseInterface {
        // Before: Log the request
        error_log("Request: {$request->getMethod()} {$request->getUri()}");

        // Pass to next middleware/controller
        $response = $handler->handle($request);

        // After: Log the response
        error_log("Response: {$response->getStatusCode()}");

        return $response;
    }
}

Registering Middleware

Add middleware to the application:

php
use App\Middleware\LoggingMiddleware;
use App\Middleware\AuthMiddleware;

$app->pipe(new LoggingMiddleware());
$app->pipe(new AuthMiddleware());

Middleware runs in the order registered.

Callable Middleware

Use closures for simple middleware:

php
$app->pipe(function ($request, $handler) {
    $response = $handler->handle($request);
    return $response->withHeader('X-Powered-By', 'Lighthouse');
});

Authentication Example

php
<?php

namespace App\Middleware;

use Lighthouse\Http\Response;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AuthMiddleware implements MiddlewareInterface
{
    public function process(
        ServerRequestInterface $request,
        RequestHandlerInterface $handler
    ): ResponseInterface {
        $token = $request->getHeaderLine('Authorization');

        if (!$this->isValid($token)) {
            return new Response(401);
        }

        // Add user to request attributes
        $request = $request->withAttribute('user', $this->getUser($token));

        return $handler->handle($request);
    }

    private function isValid(string $token): bool
    {
        // Validate token...
        return $token !== '';
    }

    private function getUser(string $token): array
    {
        // Fetch user from token...
        return ['id' => 1, 'name' => 'John'];
    }
}

CORS Example

php
<?php

namespace App\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class CorsMiddleware implements MiddlewareInterface
{
    public function process(
        ServerRequestInterface $request,
        RequestHandlerInterface $handler
    ): ResponseInterface {
        $response = $handler->handle($request);

        return $response
            ->withHeader('Access-Control-Allow-Origin', '*')
            ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
            ->withHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    }
}

Modifying the Request

Pass data to downstream handlers via attributes:

php
public function process($request, $handler): ResponseInterface
{
    $request = $request->withAttribute('startTime', microtime(true));

    return $handler->handle($request);
}

Access in controllers:

php
$startTime = $request->getAttribute('startTime');

Released under the MIT License.