Slim 4 How to "short circuit" Middleware?

Created on 26 Apr 2019  路  2Comments  路  Source: slimphp/Slim

With the double-pass function signature ($request, $response, $next) being removed from middleware in Slim 4 I'm trying to figure out how to short circuit the middleware chain. See #2335 for an other explanation of how this is done in Slim 3.
For my example I am using the double pass function to check for a valid API key in middleware. If the API key isn't valid then I return a response indicating an error status. If the API key is valid then I would simply call $next($request, $response) which continues the middleware chain.
The question is how do I short circuit the middleware in Slim 4?

Slim 4

Most helpful comment

You just return the response early without calling $handler->handle($request). Essentially $handler->handle($request) is the equivalent of $next($request, $response);

<?php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;

class MyMiddleware implements MiddlewareInterface {
    public function process(Request $request, RequestHandler $handler): ResponseInterface
    {
        if ($conditionToShortCircuit) {
            $response = new Response();
            $response->getBody()->write('Short circuit');
            return $response;
        }

        // Keep processing middleware queue as normal
        return $handler->handle($request);
    }
}

All 2 comments

You just return the response early without calling $handler->handle($request). Essentially $handler->handle($request) is the equivalent of $next($request, $response);

<?php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;

class MyMiddleware implements MiddlewareInterface {
    public function process(Request $request, RequestHandler $handler): ResponseInterface
    {
        if ($conditionToShortCircuit) {
            $response = new Response();
            $response->getBody()->write('Short circuit');
            return $response;
        }

        // Keep processing middleware queue as normal
        return $handler->handle($request);
    }
}

Note that to stay decoupled from the PSR7-implementation used, you could write your middleware as follows

<?php

declare(strict_types=1);

namespace App;

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

class MyMiddleware implements MiddlewareInterface
{
    /**
     * @var ResponseFactoryInterface
     */
    private $responseFactory;

    /**
     * @param ResponseFactoryInterface $responseFactory
     */
    public function __construct(ResponseFactoryInterface $responseFactory)
    {
        $this->responseFactory = $responseFactory;
    }

    /**
     * @inheritDoc
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        if ($conditionToShortCircuit) {
            $response = $this->responseFactory->createResponse();
            $response->getBody()->write('Short circuit');

            return $response;
        }

        // Keep processing middleware queue as normal
        return $handler->handle($request);
    }
}

and upon instantiation you pass the response factory to the middleware

<?php

declare(strict_types=1);

use App\MyMiddleware;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

$app->addMiddleware(new MyMiddleware($app->getResponseFactory()));
$app->addRoutingMiddleware();
$app->addErrorMiddleware(true, true, false);

$app->get('/', function (Request $request, Response $response, array $args): Response {
    return $response;
});

$app->run();
Was this page helpful?
0 / 5 - 0 ratings

Related issues

l0gicgate picture l0gicgate  路  50Comments

l0gicgate picture l0gicgate  路  83Comments

zyx-rd picture zyx-rd  路  19Comments

konskript picture konskript  路  62Comments

codeguy picture codeguy  路  43Comments