Giter Club home page Giter Club logo

leaky-bucket-rate-limiter's Introduction

PSR-7 Leaky Bucket Rate Limiter

This middleware enables API Rate-Limiting based on a Leaky Bucket algorithm.

Usage

To get started, you can easily use composer:

composer require robwittman/leaky-bucket-rate-limiter

Once installed, require the package, apply some settings, and start limiting.

<?php

require_once('vendor/autoload.php');

use LeakyBucketRateLimiter\RateLimiter;

$slim = \Slim\App();

$slim->add(new RateLimiter([
    'callback' => function(RequestInterface $request) {
        return [
            'token' => <token>
        ];
    },
    'throttle' => function(ResponseInterface $response) {
        return $response->withStatus(429)->withJson([
            'error' => "User request limit reached"
        ]);
    }
]))

$slim->run();

The only required settings to use RateLimiter is a callback and throttle.

Examples

IP Address
$slim->add(new RateLimiter([
    'callback' => function(RequestInterface $request) {
        return [
            'token' => $_SERVER['REMOTE_ADDR']
        ];
    }
]));
Session ID
$slim->add(new RateLimiter([
    'callback' => function(RequestInterface $request) {
        return [
            'token' => session_id()
        ];
    }
]));
Request Attribute
$slim->add(new RateLimiter([
    'callback' => function(RequestInterface $request) {
        return [
            'token' => $request->getAttribute('<token_or_uid>')
        ];
    },
]));

Once the bucket has a token to act on, it communicates with Redis to keep track of traffic. If the token is over it's request limit, it will trigger the throttle function passed to the constructor.

Parameters

Callback (required)

The callback argument is called when the Limiter needs a key to check. It passes along the Request object, and can either return an array with a (string) 'token' key, or can return TRUE to skip rate limiting

$slim->add(new RateLimiter([
    'callback' => function(RequestInterface $request) {
        return [
            'token' => session_id()
        ];
    }
]))

Throttle (required)

Tell the Limiter how to respond to throttled requests

$slim->add(new RateLimiter([
    'throttle' => function(ResponseInterface $response) {
        return $response->withStatus(429)->withJson([
            'message' => "Dude, you gotta slow down"
        ]);
    };
]));

NOTE All further settings assume callback and throttle parameters are already set

Capacity and Leak

Capacity is the total amount of drips (requests) the bucket may contain. Leak is the amount of drips per second that you want to remove from the bucket

$slim->add(new RateLimiter([
    'capacity' => 45,
    'leak' => 1
]));

Ignored routes

You can pass an array of routes that you do not want to rate limit. This completely bypasses the rate limit middleware, so they will not have respective headers either

$slim->add(new RateLimiter([
    'ignore' => [
        'auth/token',
        'users/me',
        'other/ignored/routes'
    ]
]));

Prefix / Postfix

Provide a prefix / suffix for the bucket key. The key will be stored in Redis as PREFIX.key.SUFFIX

$slim->add(new RateLimiter([
    'prefix' => 'bucket-o-leaks',
    'suffix' => "limiter"
]));

Header

Specify what header to provide, containing Rate Limiting info. Set to false to disable.

$slim->add(new RateLimiter([
    'header' => "Rate-Limiting-Meta"
]));

// Rate-Limiting-Meta: X / Y
// X = Current drips in bucket, Y = capacity

Storage

By default, the Rate Limiter will attempt to connect to a local redis instance at http://127.0.0.1:6379, as per Predis\Client().This can be overridden by providing either an array of settings for Predis\Client to connect with, or providing an object with methods get() and set() for storing and retrieving data (mysql, memcached, mongo, etc). If using docker-compose development container, just use redis as the hostname, and container linking will connect it.

$slim->add(new RateLimiter([
    // Rate limiter settings
], [
    'scheme' => 'tcp://',
    'host' => 'redis',
    'port' => 6379
]))

// OR

class ObjectWithGetAndSetMethods {
    public function get($key) {
        return $this->{$key};
    }
    public function set($key, $value) {
        $this->{$key} = $value;
    }
}
$storage = new ObjectWithGetAndSetMethods();
$slim->add(new RateLimiter([
    // Rate limiter settings
], $storage));

Development / Testing

This library comes packaged with a Docker environment for testing and development. If you're not using Docker, you ought to be!

To bootstrap an environment using docker-compose, simply

docker-compose up

This generates a PHP container with source code and packages, running a local dev server. It also provisions and links a Redis container to use as your storage mechanism.

If you're not using docker-compose, or want to implement a different storage system, you can launch a solo container.

docker build -t <tag-name> .

docker run -v $PWD:/opt -p "8001:8001" <container_name>

The server can be accessed at :8001, and contains a mini app to play around with. Running tests is equally as easy, and is centered around docker

docker-compose up
docker-compose exec web bash
vendor/bin/phpunit

leaky-bucket-rate-limiter's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

leaky-bucket-rate-limiter's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.