Whiskey and rants

Biased ideas about things

EventsManager and Middleware behaviour on Phalcon Framework

07 March, 2018 | Programming

One way to define middleware and to attach it to an application in Phalcon Framework is the following:

$app = new Micro($di);

$eventsManager = new EventsManager();

$eventsManager->attach('micro', new FTS\Middleware\MaintenanceMode());
$eventsManager->attach('micro', new FTS\Middleware\ValidateJsonPayload());
$eventsManager->attach('micro', new FTS\Middleware\IsRequestValid());
...

$app->setEventsManager($eventsManager)

As requested by the MiddlewareInterface (implemented by all the specified middleware), the return of the function (for example beforeHandleRoute) should be a boolean. Although this is true, one might assume that a returned value of false will break the execution of the rest of the middleware and return a specific response. Check this example:

class MaintenanceMode implements MiddlewareInterface
{
    public function beforeHandleRoute(Event $event, Micro $application): bool
    {
            $config = $application->getDI()->getConfig();
	    if ($config->MAINTENANCE_MODE) {
                $application->response->setJsonContent(['msg' => 'Maintenance mode']);
                $application->response->setStatusCode(503);
                $application->response->send();

                return false;
            }

            return true;
    }

    public function call(Micro $application): bool
    {
        return true;
    }
}

 If the configuration is triggering "maintenance mode" you expect to have a response with code 503, a nice message and the next middleware in line (in our case ValidateJsonPayload, IsRequestValid) not to be executed.

It looks that this is not the case. In reality it will go for the next middleware, and if that is also returning a HTTP Response of some sort, it will complain about already sent headers.

 

Checking the zep source code of the Micro application, it looks like the execution is stopped based on a different variable. In order to achieve this, add the following lines of code inside your "false" block:

...	
     if ($config->MAINTENANCE_MODE) {
                $application->response->setJsonContent(['msg' => 'Maintenance mode']);
                $application->response->setStatusCode(503);
                $application->response->send();

                $event->stop();  # this will stop actually the execution for the rest of the middleware	
                return false;
            }
...

 

Note: if the application is doing a redirect, then this doesn't apply. Most examples are with a redirect, therefore this problem is not raised.

Note: the code is written for Phalcon 3.2.0 as March 2018