We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Reusable Micro Middleware (before) does not stop operation?

Hi there,

I have an Access class as a Middleware for my Micro App:

namespace Api\Middleware;

use Phalcon\Mvc\Micro as PhMicro,
    Phalcon\Mvc\Micro\MiddlewareInterface;

/**
 * Class Access
 * @package Api\Middleware
 */
class Access implements MiddlewareInterface
{
    public function call(PhMicro $application)
    {
        $session  = $application['session'];

        if(!$application->session->has('identity')) {
            $application->response->unAuthorized(); // Response json error blah blah
            return false;
        }
        return true;
    }
}

but when it attached to application as follow:

$application = new \Phalcon\Mvc\Micro();
$application->before(new Api\Middleware\Access());
$application->handle();

The operation does not stop and route execute after middleware returns FALSE!

I confused cause using middleware as a closure already works:

$application = new \Phalcon\Mvc\Micro();
$application->before(function () use($application) {
    if(!$application->session->has('identity')) {
        $application->response->unAuthorized();
        return false;
    }
    return true;
});
$application->handle();

Is this a bug or something else?

P.S1: I allready use $application->stop() in middleware with no success!

P.S2: What is $this->_stopped (in this line) for?

Thanks.

I am using phalcon verson 2.1.0r . and still not able to return false from Middleware interface.

See my code : use Phalcon\Mvc\Micro as MainApp; use Phalcon\Mvc\Micro\MiddlewareInterface;

class Authentication implements MiddlewareInterface { public function call(MainApp $app) { return false;

}

}

and my index.php is as below.

<?php

use Phalcon\Loader; use Phalcon\Mvc\Micro; use Phalcon\Di\FactoryDefault; use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter; use Phalcon\Cache\Frontend\Data as FrontendData; use Phalcon\Cache\Backend\Redis as RedisDataAdaptor;

define('REDIS_ON', false);

$di = new FactoryDefault();

// Setup the database service
$di->set('db', function () {
    return new DbAdapter(array(
        "host"     => "localhost",
        "username" => "root",
        "password" => "",
        "dbname"   => "db-data"
    ));
});

$di->set('modelsCache', function () {

// Cache data for one day by default
$frontCache = new FrontendData(
    array(
        "lifetime" => 1
    )
);

 $cache = new RedisDataAdaptor($frontCache, array(
    'host' => 'localhost',
    'port' => 6379,
));
return $cache;

});

$loader = new Loader(); $loader->registerDirs(array( '../app/controllers/', '../app/models/', '../app/core/' ))->register();

$app = new Micro($di);

$app->before(new Authentication()); $app->handle();

Is there any solution?

edited Aug '16

@andresgutierrez

In 3.0.0 and 3.0.1 this is still unresolved, i.e. does not stop execution when you return false.

@ravindra-miyani sure it is, you just cannot use callable the way it was proposed. What I did instead, I built my shared service which handles some sort of validation, and I call it from $app->before() context. If the check fails, it will return false which then will stop execution for real. So the trick is to return false directly, not from callable handler.

$app->before(function () use ($app) {
return $app->validateMyCustomData->callMyCustomMethod(); //true or false
});

Ok. I did this way. It works fine. Thank you for kind help. Much appreciated.



152

I downloaded the new Phalcon site, cleared things and created an AuthMiddleware but I am not sure what call should return..it seems it doesn't really matter if true, false or void..it will not change anything..I had to move the auth logic to beforeExecuteRoute :( ..is this how this suposed to work?

Thanks @ravindra-miyani . This worked for me.

@ravindra-miyani sure it is, you just cannot use callable the way it was proposed. What I did instead, I built my shared service which handles some sort of validation, and I call it from $app->before() context. If the check fails, it will return false which then will stop execution for real. So the trick is to return false directly, not from callable handler.

$app->before(function () use ($app) {
return $app->validateMyCustomData->callMyCustomMethod(); //true or false
});

You need to use $application->stop() i think. Even in phalcon 2 there was never check for false/true, only for _stopped. If in doc there was anytime return true/false then it's docs issue i guess. https://github.com/phalcon/cphalcon/issues/10912