PHPackages                             skedli/http-middleware - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. skedli/http-middleware

ActiveLibrary[HTTP &amp; Networking](/categories/http)

skedli/http-middleware
======================

Provides PSR-15 middleware for HTTP requests, including correlation ID propagation, structured request/response logging, error handling, and stateless JWT authentication.

1.8.0(2mo ago)034↓66.7%MITPHPPHP ^8.5CI passing

Since Feb 22Pushed 2mo agoCompare

[ Source](https://github.com/skedli/http-middleware)[ Packagist](https://packagist.org/packages/skedli/http-middleware)[ Docs](https://github.com/skedli/http-middleware)[ RSS](/packages/skedli-http-middleware/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (9)Dependencies (37)Versions (11)Used By (0)

HTTP Middleware
===============

[](#http-middleware)

[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](LICENSE)

- [Overview](#overview)
- [Installation](#installation)
- [How to use](#how-to-use)
    - [Correlation ID](#correlation-id)
        - [Default usage](#default-usage)
        - [Reusing an existing correlation ID](#reusing-an-existing-correlation-id)
        - [Custom provider](#custom-provider)
        - [Integration with tiny-blocks/logger](#integration-with-tiny-blockslogger)
    - [Request and response logging](#request-and-response-logging)
        - [Default usage](#log-default-usage)
        - [What is logged](#what-is-logged)
        - [Automatic correlation ID binding](#automatic-correlation-id)
    - [Error handling](#error-handling)
        - [Default usage](#error-default-usage)
        - [Error handling settings](#error-handling-settings)
        - [Logging errors](#logging-errors)
    - [Authentication](#authentication)
        - [Default usage](#auth-default-usage)
        - [Using a JWKS endpoint](#jwks-url)
        - [Supported algorithms](#supported-algorithms)
        - [Accessing the authenticated user](#accessing-the-authenticated-user)
        - [Custom token decoder](#custom-token-decoder)
        - [Custom authenticated user](#custom-authenticated-user)
        - [Builder precedence](#builder-precedence)
- [License](#license)

Overview
--------

[](#overview)

Provides PSR-15 middleware for HTTP requests, including correlation ID propagation, structured request/response logging, error handling, and stateless JWT authentication.

Built on top of [PSR-15](https://www.php-fig.org/psr/psr-15) and [PSR-7](https://www.php-fig.org/psr/psr-7), the middleware can be used with any framework that supports the `MiddlewareInterface` standard.

Installation
------------

[](#installation)

```
composer require skedli/http-middleware
```

How to use
----------

[](#how-to-use)

### Correlation ID

[](#correlation-id)

The middleware reads the `Correlation-Id` header from the incoming request. If present and non-empty, it reuses the value. Otherwise, it generates a new UUID v4. In both cases, the correlation ID is:

- Injected as a request attribute (`correlationId`) for downstream handlers.
- Added to the response as the `Correlation-Id` header.

#### Default usage

[](#default-usage)

Create the middleware with `CorrelationIdMiddleware::create()` and register it in your application. The default provider generates a UUID v4 when no `Correlation-Id` header is present.

```
use Skedli\HttpMiddleware\CorrelationIdMiddleware;

$middleware = CorrelationIdMiddleware::create()->build();
```

In a Slim 4 application:

```
use Skedli\HttpMiddleware\CorrelationIdMiddleware;

$app->add(CorrelationIdMiddleware::create()->build());
```

The correlation ID is accessible in any handler via the request attribute:

```
use Psr\Http\Message\ServerRequestInterface;
use Skedli\HttpMiddleware\CorrelationId;

$correlationId = $request->getAttribute('correlationId');
/** @var CorrelationId $correlationId */
$correlationId->toString(); # "550e8400-e29b-41d4-a716-446655440000"
```

#### Reusing an existing correlation ID

[](#reusing-an-existing-correlation-id)

When the incoming request already contains the `Correlation-Id` header, the middleware preserves it instead of generating a new one. This enables end-to-end traceability across service boundaries.

```
Client → BFF (generates Correlation-Id: req-abc-123)
       → Service X (reuses req-abc-123)
       → Service Y (reuses req-abc-123)
       → Service Z (reuses req-abc-123)

```

No additional configuration is needed. The middleware handles this automatically.

#### Custom provider

[](#custom-provider)

Implement the `CorrelationIdProvider` interface to replace the default UUID v4 generation strategy:

```
use Skedli\HttpMiddleware\CorrelationId;
use Skedli\HttpMiddleware\CorrelationIdProvider;
use Skedli\HttpMiddleware\Internal\CorrelationId\UuidCorrelationId;

final readonly class PrefixedCorrelationIdProvider implements CorrelationIdProvider
{
    public function __construct(private string $prefix)
    {
    }

    public function generate(): CorrelationId
    {
        return UuidCorrelationId::from(value: sprintf('%s-%s', $this->prefix, bin2hex(random_bytes(8))));
    }
}
```

Then configure the middleware with the custom provider:

```
use Skedli\HttpMiddleware\CorrelationIdMiddleware;

$middleware = CorrelationIdMiddleware::create()
    ->withProvider(provider: new PrefixedCorrelationIdProvider(prefix: 'bff'))
    ->build();
```

#### Integration with tiny-blocks/logger

[](#integration-with-tiny-blockslogger)

The middleware is designed to work seamlessly with [tiny-blocks/logger](https://github.com/tiny-blocks/logger). Extract the correlation ID from the request attribute and bind it to the logger context:

```
use Psr\Http\Message\ServerRequestInterface;
use Skedli\HttpMiddleware\CorrelationId;
use TinyBlocks\Logger\LogContext;
use TinyBlocks\Logger\Logger;

final readonly class CreateUserHandler
{
    public function __construct(private Logger $logger)
    {
    }

    public function __invoke(ServerRequestInterface $request): void
    {
        /** @var CorrelationId $correlationId */
        $correlationId = $request->getAttribute('correlationId');

        $logger = $this->logger->withContext(
            context: LogContext::from(correlationId: $correlationId->toString())
        );

        $logger->info(message: 'user.creating', context: ['email' => 'john@example.com']);
    }
}
```

Output:

```
2026-02-21T16:00:00+00:00 component=identity correlation_id=550e8400-e29b-41d4-a716-446655440000 level=INFO key=user.creating data={"email":"jo**@example.com"}

```

### Request and response logging

[](#request-and-response-logging)

The `LogMiddleware` provides structured logging for every HTTP request and response. It captures method, URI, query parameters, body, status code, and duration automatically.

#### Default usage

[](#default-usage-1)

Create the middleware with a [tiny-blocks/logger](https://github.com/tiny-blocks/logger) instance:

```
use Skedli\HttpMiddleware\LogMiddleware;
use TinyBlocks\Logger\Logger;

$middleware = LogMiddleware::create(logger: $logger);
```

In a Slim 4 application:

```
use Skedli\HttpMiddleware\LogMiddleware;

$app->add(LogMiddleware::create(logger: $logger));
```

#### What is logged

[](#what-is-logged)

The middleware logs two entries per request cycle, one for the incoming **request** and one for the outgoing \*\*response \*\*.

**Request** is always logged at `info` level:

```
level=INFO key=request data={"method":"POST","uri":"/api/users","query_parameters":{"page":"1"},"body":{"name":"John","email":"john@example.com"}}

```

**Response** is logged at `info` for success (2xx/3xx) and `error` for failures (4xx/5xx):

```
level=INFO key=response data={"method":"POST","uri":"/api/users","status_code":201,"duration_ms":45.32,"body":{"id":"550e8400","name":"John"}}

```

```
level=ERROR key=response data={"method":"POST","uri":"/api/users","status_code":422,"duration_ms":12.87,"body":{"error":"Validation failed"}}

```

The `query_parameters` and `body` fields are **only included when present**. A `GET` request without query parameters or body produces a minimal log:

```
level=INFO key=request data={"method":"GET","uri":"/api/health"}
level=INFO key=response data={"method":"GET","uri":"/api/health","status_code":200,"duration_ms":1.04}

```

#### Automatic correlation ID binding

[](#automatic-correlation-id-binding)

When used together with the `CorrelationIdMiddleware`, the `LogMiddleware` automatically binds the correlation ID to the logger context. No additional configuration is needed, just register both middleware in the correct order:

```
use Skedli\HttpMiddleware\CorrelationIdMiddleware;
use Skedli\HttpMiddleware\LogMiddleware;

// In Slim 4, middleware executes in LIFO order (last added = first to run).
// CorrelationIdMiddleware must run before LogMiddleware.
$app->add(LogMiddleware::create(logger: $logger));
$app->add(CorrelationIdMiddleware::create()->build());
```

The correlation ID is then automatically included in every log entry:

```
2026-02-24T10:00:00+00:00 component=identity correlation_id=550e8400-e29b-41d4-a716-446655440000 level=INFO key=request data={"method":"POST","uri":"/api/users","body":{"name":"John"}}
2026-02-24T10:00:00+00:00 component=identity correlation_id=550e8400-e29b-41d4-a716-446655440000 level=INFO key=response data={"method":"POST","uri":"/api/users","status_code":201,"duration_ms":45.32}

```

If the `CorrelationIdMiddleware` is not registered, the `LogMiddleware` works normally without the correlation ID.

### Error handling

[](#error-handling)

The `ErrorMiddleware` catches uncaught exceptions during request processing and transforms them into structured JSON responses. Error logging and response detail exposure are fully configurable through `ErrorHandlingSettings`.

When used together with the `CorrelationIdMiddleware`, the `ErrorMiddleware` automatically binds the correlation ID to the error log context. No additional configuration is needed, just register both middleware in the correct order.

#### Default usage

[](#default-usage-2)

Register the middleware to automatically catch exceptions. If the exception contains a valid HTTP error code (4xx or 5xx), it is used, otherwise, it defaults to **500 Internal Server Error**.

By default, error details are not displayed in the response and errors are not logged.

```
use Skedli\HttpMiddleware\ErrorMiddleware;

$middleware = ErrorMiddleware::create()->build();
```

Response body:

```
{
    "error": "Unexpected database error"
}
```

#### Error handling settings

[](#error-handling-settings)

Use `ErrorHandlingSettings` to control how errors are displayed and logged:

SettingDefaultDescription`logErrors``false`Enables logging of exceptions when a logger is provided.`logErrorDetails``false`Includes exception class, file, line, and stack trace in the log context.`displayErrorDetails``false`Includes exception class, file, line, and stack trace in the response body.**Development** full visibility in response and logs:

```
use Skedli\HttpMiddleware\ErrorMiddleware;
use Skedli\HttpMiddleware\Internal\Error\ErrorHandlingSettings;

$middleware = ErrorMiddleware::create()
    ->withLogger(logger: $logger)
    ->withSettings(settings: ErrorHandlingSettings::from(
        logErrors: true,
        logErrorDetails: true,
        displayErrorDetails: true
    ))
    ->build();
```

Response body:

```
{
    "error": "Unexpected database error",
    "exception": "RuntimeException",
    "file": "/app/src/Application/Handlers/UserCreatingHandler.php",
    "line": 42,
    "trace": [
        "#0 /app/src/Driver/Http/Endpoints/User/CreateUser.php(25): ...",
        "#1 /app/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponseArgs.php(30): ..."
    ]
}
```

Log output:

```
correlation_id=550e8400-e29b-41d4-a716-446655440000 level=ERROR key=error data={"message":"Unexpected database error","exception":"RuntimeException","file":"/app/src/...","line":42,"trace":"#0 /app/src/..."}

```

**Production** log with details, minimal response:

```
use Skedli\HttpMiddleware\ErrorMiddleware;
use Skedli\HttpMiddleware\Internal\Error\ErrorHandlingSettings;

$middleware = ErrorMiddleware::create()
    ->withLogger(logger: $logger)
    ->withSettings(settings: ErrorHandlingSettings::from(
        logErrors: true,
        logErrorDetails: true,
        displayErrorDetails: false
    ))
    ->build();
```

Response body:

```
{
    "error": "Unexpected database error"
}
```

Log output:

```
correlation_id=550e8400-e29b-41d4-a716-446655440000 level=ERROR key=error data={"message":"Unexpected database error","exception":"RuntimeException","file":"/app/src/...","line":42,"trace":"#0 /app/src/..."}

```

#### Logging errors

[](#logging-errors)

To enable error logging, provide a [tiny-blocks/logger](https://github.com/tiny-blocks/logger) instance **and** enable `logErrors` in the settings. The logger alone is not sufficient, `logErrors` must be explicitly enabled.

```
use Skedli\HttpMiddleware\ErrorMiddleware;
use Skedli\HttpMiddleware\Internal\Error\ErrorHandlingSettings;

$middleware = ErrorMiddleware::create()
    ->withLogger(logger: $logger)
    ->withSettings(settings: ErrorHandlingSettings::from(
        logErrors: true,
        logErrorDetails: false,
        displayErrorDetails: false
    ))
    ->build();
```

Log output:

```
correlation_id=550e8400-e29b-41d4-a716-446655440000 level=ERROR key=error data={"message":"Unexpected database error"}

```

If the `CorrelationIdMiddleware` is not registered, the `ErrorMiddleware` works normally without the correlation ID.

### Authentication

[](#authentication)

The `AuthenticationMiddleware` enforces stateless token-based authentication on incoming requests. It extracts the Bearer token from the `Authorization` header, validates it using a `TokenDecoder`, and propagates the authenticated user context as a request attribute.

No database access is performed validation relies exclusively on the token's cryptographic signature and its claims.

#### Default usage

[](#default-usage-3)

Configure the middleware with a signing algorithm and key material. The built-in `JwtTokenDecoder` handles JWT validation using [firebase/php-jwt](https://github.com/firebase/php-jwt).

**With RSA (asymmetric):**

```
use Skedli\HttpMiddleware\AuthenticationMiddleware;
use Skedli\HttpMiddleware\SigningAlgorithm;

$middleware = AuthenticationMiddleware::create()
    ->withAlgorithm(algorithm: SigningAlgorithm::RS256)
    ->withKeyMaterial(keyMaterial: $publicKey)
    ->build();
```

**With HMAC (symmetric):**

```
use Skedli\HttpMiddleware\AuthenticationMiddleware;
use Skedli\HttpMiddleware\SigningAlgorithm;

$middleware = AuthenticationMiddleware::create()
    ->withAlgorithm(algorithm: SigningAlgorithm::HS256)
    ->withKeyMaterial(keyMaterial: 'your-shared-secret-key')
    ->build();
```

In a Slim 4 application:

```
use Skedli\HttpMiddleware\AuthenticationMiddleware;
use Skedli\HttpMiddleware\SigningAlgorithm;

$app->add(
    AuthenticationMiddleware::create()
        ->withAlgorithm(algorithm: SigningAlgorithm::RS256)
        ->withKeyMaterial(keyMaterial: $publicKey)
        ->build()
);
```

#### Using a JWKS endpoint

[](#using-a-jwks-endpoint)

In a microservices architecture, the Identity Provider (IdP) typically exposes its public keys through a [JWKS](https://datatracker.ietf.org/doc/html/rfc7517) endpoint. The middleware can fetch the public key directly from this endpoint, eliminating the need to manually distribute key material across services.

```
use Skedli\HttpMiddleware\AuthenticationMiddleware;

$middleware = AuthenticationMiddleware::create()
    ->withJwksUrl(jwksUrl: 'http://identity-web/v1/keys/public')
    ->build();
```

The JWKS fetch is **lazy** — no network call is made during `build()`. The public key is resolved on the first incoming request and cached for the lifetime of the middleware instance. The algorithm defaults to `RS256` when not explicitly set.

By default, the HTTP timeout for the JWKS fetch is **5 seconds**. You can override it with `withHttpTimeout()`:

```
use Skedli\HttpMiddleware\AuthenticationMiddleware;
use Skedli\HttpMiddleware\Internal\HttpTimeout;

$middleware = AuthenticationMiddleware::create()
    ->withJwksUrl(jwksUrl: 'http://identity-web/v1/keys/public')
    ->withHttpTimeout(httpTimeout: HttpTimeout::inSeconds(10))
    ->build();
```

In a Slim 4 application with an environment variable:

```
use Skedli\HttpMiddleware\AuthenticationMiddleware;
use TinyBlocks\EnvironmentVariable\EnvironmentVariable;

$jwksUrl = EnvironmentVariable::from(name: 'IDENTITY_JWKS_URL')->toString();

$app->add(
    AuthenticationMiddleware::create()
        ->withJwksUrl(jwksUrl: $jwksUrl)
        ->build()
);
```

When the JWKS endpoint is unreachable or returns an invalid response, the middleware returns a `401 Unauthorized`response with a descriptive error message.

When authentication fails, the middleware returns a `401 Unauthorized` response:

```
{
    "code": "TOKEN_VALIDATION_FAILED",
    "message": "Token has expired."
}
```

Possible error messages:

MessageCause`Missing Authorization header.`The request has no `Authorization` header.`Authorization header must use Bearer scheme.`The header does not start with `Bearer `.`Bearer token is empty.`The header is `Bearer` with no token value.`Token is invalid or could not be decoded.`The token is malformed or the signature does not match.`Token has expired.`The token `exp` claim is in the past.`Token is missing the subject (sub) claim.`The token has no `sub` claim.`Failed to fetch JWKS from : .`The JWKS endpoint is unreachable or timed out.`Invalid JWKS response from .`The JWKS JSON has no keys.`JWKS response does not contain a valid RSA key (...).`The JWKS key is missing the `n` or `e` fields.#### Supported algorithms

[](#supported-algorithms)

The `SigningAlgorithm` enum defines the supported algorithms:

AlgorithmTypeUse case`RS256`RSAAsymmetric — public/private key.`RS384`RSAAsymmetric — public/private key.`RS512`RSAAsymmetric — public/private key.`HS256`HMACSymmetric — shared secret.`HS384`HMACSymmetric — shared secret.`HS512`HMACSymmetric — shared secret.`ES256`ECDSAAsymmetric — elliptic curve.`ES384`ECDSAAsymmetric — elliptic curve.

#### Accessing the authenticated user

[](#accessing-the-authenticated-user)

On successful authentication, the middleware injects an `AuthenticatedUser` instance as a request attribute. The `AuthenticatedUser` is an interface with three methods:

```
use Psr\Http\Message\ServerRequestInterface;
use Skedli\HttpMiddleware\AuthenticatedUser;
use Skedli\HttpMiddleware\AuthenticationMiddleware;

/** @var AuthenticatedUser $user */
$user = $request->getAttribute(AuthenticationMiddleware::AUTHENTICATED_USER_ATTRIBUTE);

$user->userId();    # "e3b0c442-98fc-1c14-b39f-f32d831cb27a"
$user->issuedAt();  # 1740000000
$user->expiresAt(); # 1740003600
```

#### Custom token decoder

[](#custom-token-decoder)

Implement the `TokenDecoder` interface to replace the built-in JWT validation with your own strategy. The decoder must validate the token locally (stateless), without performing any network call or database query.

```
use Skedli\HttpMiddleware\AuthenticatedUser;
use Skedli\HttpMiddleware\TokenDecoder;
use Skedli\HttpMiddleware\Internal\Authentication\TokenValidationFailed;

final readonly class OpaqueTokenDecoder implements TokenDecoder
{
    public function __construct(private TokenStore $tokenStore)
    {
    }

    public function decode(string $token): AuthenticatedUser
    {
        $claims = $this->tokenStore->lookup($token);

        if ($claims === null) {
            throw TokenValidationFailed::withReason(reason: 'Token not found.');
        }

        return MyAuthenticatedUser::from(claims: $claims);
    }
}
```

Then configure the middleware with the custom decoder:

```
use Skedli\HttpMiddleware\AuthenticationMiddleware;

$middleware = AuthenticationMiddleware::create()
    ->withTokenDecoder(tokenDecoder: new OpaqueTokenDecoder($tokenStore))
    ->build();
```

#### Custom authenticated user

[](#custom-authenticated-user)

The `AuthenticatedUser` is an interface, so you can extend it with additional claims specific to your domain. Return your custom implementation from your `TokenDecoder`:

```
use Skedli\HttpMiddleware\AuthenticatedUser;

final readonly class TenantAwareUser implements AuthenticatedUser
{
    public function __construct(
        private string $userId,
        private int $issuedAt,
        private int $expiresAt,
        private string $tenantId,
        private array $roles
    ) {
    }

    public function userId(): string
    {
        return $this->userId;
    }

    public function issuedAt(): int
    {
        return $this->issuedAt;
    }

    public function expiresAt(): int
    {
        return $this->expiresAt;
    }

    public function tenantId(): string
    {
        return $this->tenantId;
    }

    public function roles(): array
    {
        return $this->roles;
    }
}
```

Access the extended claims in your handler:

```
use Psr\Http\Message\ServerRequestInterface;
use Skedli\HttpMiddleware\AuthenticationMiddleware;

/** @var TenantAwareUser $user */
$user = $request->getAttribute(AuthenticationMiddleware::AUTHENTICATED_USER_ATTRIBUTE);

$user->userId();   # "e3b0c442-98fc-1c14-b39f-f32d831cb27a"
$user->tenantId(); # "tenant-42"
$user->roles();    # ["admin", "billing"]
```

#### Builder precedence

[](#builder-precedence)

When multiple configuration options are provided, the builder resolves them in this order:

PriorityConfigurationBehavior1st`withTokenDecoder(...)`Custom decoder wins everything else is ignored.2nd`withJwksUrl(...)`Fetches JWKS, converts to PEM, defaults to RS256.3rd`withKeyMaterial(...)` + `withAlgorithm(...)`Uses PEM and algorithm directly.```
use Skedli\HttpMiddleware\AuthenticationMiddleware;
use Skedli\HttpMiddleware\SigningAlgorithm;

// The custom decoder wins, JWKS URL, key material, and algorithm are ignored.
$middleware = AuthenticationMiddleware::create()
    ->withJwksUrl(jwksUrl: 'http://identity-web/v1/keys/public')
    ->withAlgorithm(algorithm: SigningAlgorithm::RS256)
    ->withKeyMaterial(keyMaterial: $publicKey)
    ->withTokenDecoder(tokenDecoder: $customDecoder)
    ->build();
```

Building the middleware without a `TokenDecoder`, key material, or JWKS URL throws a `TokenValidationFailed` exception. Using key material without an algorithm also throws.

License
-------

[](#license)

HTTP Middleware is licensed under [MIT](LICENSE).

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance86

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 90.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

9

Last Release

74d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/b00a83241d2af272255f1755bf6aff48e77821c59ef623520176d9e828977241?d=identicon)[gustavofreze](/maintainers/gustavofreze)

---

Top Contributors

[![gustavofreze](https://avatars.githubusercontent.com/u/22873481?v=4)](https://github.com/gustavofreze "gustavofreze (10 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

correlation-idhttp-middlewarejwtphppsr-15psr-7skedlipsr-7jwtmiddlewareAuthenticationpsr-15correlation-idhttp-middlewareskedlix-correlation-id

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/skedli-http-middleware/health.svg)

```
[![Health](https://phpackages.com/badges/skedli-http-middleware/health.svg)](https://phpackages.com/packages/skedli-http-middleware)
```

###  Alternatives

[jimtools/jwt-auth

PSR-15 JWT Authentication middleware, A replacement for tuupola/slim-jwt-auth

20142.3k3](/packages/jimtools-jwt-auth)[relay/relay

A PSR-15 server request handler.

3302.1M86](/packages/relay-relay)[mezzio/mezzio-authentication

Authentication middleware for Mezzio and PSR-7 applications

121.6M26](/packages/mezzio-mezzio-authentication)[mezzio/mezzio-authentication-oauth2

OAuth2 (server) authentication middleware for Mezzio and PSR-7 applications.

28483.0k2](/packages/mezzio-mezzio-authentication-oauth2)[middlewares/http-authentication

Middleware to implement Basic and Digest Http authentication

35302.0k2](/packages/middlewares-http-authentication)[httpsoft/http-runner

Running PSR-7 components and building PSR-15 middleware pipelines

1455.0k5](/packages/httpsoft-http-runner)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
