Javier Trejo
Javier Trejo

Reputation: 33

Silex application before middleware cancel route

I can't found the way to cancel the action inside a "Before Middleware" and send the response to the cliente without execute the controller.

For example:

$app->before( function( Request $request ) {
    // Do something here
    // ...
    // Here sent the response to the client and don't execute the controller
}});

Is possible?

One example

This code works fine. I'm looking for another solution using the framework built-in methods. If no possible, no problem.

$app->before( function( Request $request ) {
    // Do something here
    // ...

    header( 'Content-Type: application/json' );

    echo json_encode( array(
        'message' => 'Invalid token'
    ) );

    http_response_code( 400 ); // This code return Bad Request to client
    exit; // Cancel the rest of the framework
}});

Upvotes: 3

Views: 1197

Answers (2)

oshell
oshell

Reputation: 9123

If you want to cancel your request immediately and return a 400 response make use of exceptions. In your case the user is unauthorized so something like 401 would fit.

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Symfony\Component\HttpFoundation\Response;

$app->match('/', function () use ($app) {
    $app->before(function (Request $request) {
        $loggedIn= false;

        if (!$loggedIn) {
             throw new UnauthorizedHttpException(null,'unauthorized',null,Response::HTTP_UNAUTHORIZED);
        }
    });
});

$app->error(function (\Exception $e, Request $request, $code) {
    $message = strlen($e->getMessage()) > 0 ? $e->getMessage() : null;
    switch ($code) {
        case Response::HTTP_UNAUTHORIZED:
            $response = new Response($message, Response::HTTP_UNAUTHORIZED);
            break;
        default:
            $response = new Response($message, Response::HTTP_NOT_FOUND);
            break;
    }
    return $response;
});

Upvotes: 1

mTorres
mTorres

Reputation: 3590

Did you check the official documentation? From the middleware docs:

Short-circuiting the Controller

If a before middleware returns a Response object, the request handling is short-circuited (the next middleware won't be run, nor the route callback), and the Response is passed to the after middleware right away:

$app->before(function (Request $request) {
  // redirect the user to the login screen if access to the Resource is protected
  if (...) {
      return new RedirectResponse('/login');
  }
});

If you return a Response object it should work and not call the controller.

Upvotes: 0

Related Questions