akrabat / ip-address-middleware

PSR-7 Middleware that determines the client IP address and stores it as an ServerRequest attribute
Other
168 stars 38 forks source link

The middleware is not working with other middleware #6

Closed PauloPhagula closed 8 years ago

PauloPhagula commented 8 years ago

I'm trying to setup a set middleware to mangle requests and response on my app and I've noticed that I don't have the ip_address set on middleware following rka-ip-address-middleware.

More specifically I'm setting up a throttling middleware to limit requests per IP address per hour like bellow

class ThrottlingMiddleware {

    const CACHE_PREFIX = 'throttling_';
    const THROTTLING_LIMIT = 1000000;
    private $enabled = false;
    protected $memcache;

    public function __construct() {
        $this->memcache = new Memcache();
        $this->enabled = true;
    }

    private function _isRateExceeded($host) {
        if (!$this->memcache->get(self::CACHE_PREFIX . $host))
            return false;

        return $this->memcache->get(self::CACHE_PREFIX . $host) > self::THROTTLING_LIMIT;
    }

    private function _register($host) {
        if (!$this->memcache->get(self::CACHE_PREFIX . $host)) {
            $this->memcache->set(self::CACHE_PREFIX . $host, 0, time() + (60 * 60));
        }

        $this->memcache->increment(self::CACHE_PREFIX . $host, 1);
    }

    function __invoke(Request $request, Response $response, callable $next) {
        if (!$this->enabled)
            return $next($request, $response);

        $ip_address = $request->getAttribute('ip_address'); // **IP WAS SUPPOSED TO BE SET HERE**

        if (is_null($ip_address))
            return $next($request, $response);

        if ($this->_isRateExceeded($ip_address)) {
            return $response->withStatus(429, "Too Many Requests");
        }

        $response = $next($request, $response);

        $this->_register($ip_address);
        return $response;
    }
}

Then middleware is added to the app like

$checkProxyHeaders = true;
$trustedProxies = ['10.0.0.1', '10.0.0.2'];
$app->add(new RKA\Middleware\IpAddress($checkProxyHeaders, $trustedProxies));
$app->add(new ThrottlingMiddleware());

Given the above I think IpAddress is supposed to run first and thus set the ip address on the request which is received by the next middleware in the queue.

Please clarify if the assumption above is correct or not, or provide advise on how I can handle this case.

JoeBengalen commented 8 years ago
$checkProxyHeaders = true;
$trustedProxies = ['10.0.0.1', '10.0.0.2'];
$app->add(new ThrottlingMiddleware());
$app->add(new RKA\Middleware\IpAddress($checkProxyHeaders, $trustedProxies));

Please read the docs http://www.slimframework.com/docs/concepts/middleware.html

PauloPhagula commented 8 years ago

According to the docs

The last middleware layer added is the first to be executed.

Thanks