Documentation

Middleware provide a convenient mechanism for inspecting and filtering HTTP requests entering your application. For example, Laravel includes a middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware will redirect the user to your application’s login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.

For example, CrowPHP by default uses a routing middleware and an exception handling middleware, CrowPHP follows PSR-15 standard for middlewares so you can also use many readily available middlewares that implement Psr\Http\Server\MiddlewareInterface and its also very easy to write your custom middleware for example, a logging middleware might log all incoming requests to your application.

Defining a middleware

To create a new middleware, create a new PHP file and for this example we will call it EnsureTokenIsValid.php. We will create a new class EnsureTokenIsValid that implements

<?php
namespace Middlewares;

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

class EnsureTokenIsValid implements MiddlewareInterface
{

    public function process(
        ServerRequestInterface $request, 
        RequestHandlerInterface $handler): ResponseInterface
    {
        if ($request->getHeader('token') !== 'my-secret-token') {
            return new Response(403);
        }
        return $handler->handle($request);
    }
}

Now we can apply our new middleware to any route by simply calling middleware method after the route.


$router->post('/posts', function (RequestInterface $request, ResponseInterface $response) {
    $response->getBody()->write('valid token');
    return $response;
})->middleware(new EnsureTokenIsValid());

In the example above we are applying the middleware that is following PSR-15 standards you can also pass callables instead.

$router->post('/post', function (RequestInterface $request, ResponseInterface $response) {
    $response->getBody()->write('My Post');
    return $response;
})->middleware(function (RequestInterface $request, RequestHandlerInterface $next) {
    echo "Logging here in the /post request\n";
    return $next->handle($request);
}));

Types of middlewares

CrowPHP has different types of middlewares and its important to understand them since they can be used for different purposes.

  • Global Middlewares
  • Group-level Middlewares
  • Route-level Middlewares

In the examples above we have learned about the Route-level middlewares, what if you want to apply the same middleware to multiple routes and that’s where Group-level middlewares comes in to the rescue.

We can create a route group and after the first two required arguments we can pass an n number of arguments on route-group for middlewares which can be again a PSR-15 standard middleware or a callable. All of the middlewares passed will be executed in the sequence that they are passed to the route-group before finally passing the request to the request handler function of each route inside the group and ofcourse it can be nested with more middlewares passed to the sub routes or sub-groups with in.


$router->addGroup('/admin', function (RouterInterface $router) {
    $router->get('/posts/id/{id}', function (
        RequestInterface $request, 
        ResponseInterface $response, $id): ResponseInterface {

        $response->getBody()->write(json_encode(["post_id" => $id]));
        return $response->withHeader('Content-Type', 'application/json')->withStatus(403);
    })->middleware(function (RequestInterface $request, RequestHandlerInterface $next) {
        echo "This is a local middleware 1 for sunny\n";
        return $next->handle($request);
    });

    $router->get('/comments/id/{id}', function (
        RequestInterface $request, 
        ResponseInterface $response, $id): ResponseInterface {
        $response->getBody()->write('comments ' . $id);
        throw new Exception('Hey i am an exception');
    });

}, function (RequestInterface $request, RequestHandlerInterface $next) {
    echo "This is a group middleware 1\n";
    return $next->handle($request);
}, function (RequestInterface $request, RequestHandlerInterface $next) {
    echo "This is a group middleware 2\n";
    return $next->handle($request);
});

Last but not the least are the global middlewares and as the name suggests these middlewares are applied to all the requests that enter the server. To define the global middleware we use the use method on the app instance of CrowServer.

$app->use(function (RequestInterface $request, RequestHandlerInterface $next) {
    echo "This is a global middleware 1\n";
    return $next->handle($request);
});

$app->use(function (RequestInterface $request, RequestHandlerInterface $next) {
    echo "This is a global middleware 2\n";
    return $next->handle($request);
});

Like other middlewares you can pass PSR-15 compliant middlewares or callables to the use method and the execution will be in the sequence in which they are passed.