Steve Kemp

NAME

CGI::Application::Plugin::Throttle - Rate-Limiting for CGI::Application-based applications, using Redis for persistence.

SYNOPSIS

  use CGI::Application::Plugin::Throttle;


  # Your application
  sub setup {
    ...

    # Create a redis handle
    my $redis = Redis->new();

    # Configure throttling
    $self->throttle()->configure( redis => $redis,
                                  prefix => "REDIS:KEY:PREFIX",
                                  limit => 100,
                                  period => 60,
                                  exceeded => "slow_down_champ" );

DESCRIPTION

This module allows you to enforce a throttle on incoming requests to your application, based upon the remote IP address.

This module stores a count of accesses in a Redis key-store, and once hits from a particular source exceed the specified threshold the user will be redirected to the run-mode you've specified.

POTENTIAL ISSUES / CONCERNS

Users who share IP addresses, because they are behind a common-gateway for example, will all suffer if the threshold is too low. We attempt to mitigate this by building the key using a combination of the remote IP address, and the remote user-agent.

This module will apply to all run-modes, because it seems likely that this is the most common case. If you have a preference for some modes to be excluded please do contact the author.

METHODS

import

Force the throttle method into the caller's namespace, and configure the prerun hook which is used by CGI::Application.

new

This method is used internally, and not expected to be invoked externally.

The defaults are setup here, although they can be overridden in the "configure" method.

throttle

Gain access to an instance of this class. This is the method by which you can call methods on this plugin from your CGI::Application derived-class.

_get_redis_key

Build and return the Redis key to use for this particular remote request.

The key is built from the prefix string set in "configure" method, along with:

  • The remote IP address of the client.

  • The remote HTTP Basic-Auth username of the client.

  • The remote User-Agent.

count

Return the number of times the remote client has hit a run mode, along with the maximum allowed visits:

      sub your_run_mode
      {
          my ($self) = (@_);

          my( $count, $max ) = $self->throttle()->count();
          return( "$count visits seen - maximum is $max." );
      }

throttle_callback

This method is invoked by CGI::Application, as a hook.

The method is responsible for determining whether the remote client which triggered the current request has exceeded their request threshold.

If the client has made too many requests their intended run-mode will be changed to to redirect them.

configure

This method is what the user will invoke to configure the throttle-limits.

It is expected that within the users CGI::Application "setup" in CGI::Application method there will be code similar to this:

    sub setup {
        my $self = shift;

        my $r = Redis->new();

        $self->throttle()->configure( redis => $r,
                                      # .. other options here
                                    )
    }

The arguments hash contains the following known keys:

redis

A Redis handle object.

limit

The maximum number of requests that the remote client may make, in the given period of time.

period

The period of time which requests are summed for. The period is specified in seconds and if more than limit requests are sent then the client will be redirected.

prefix

This module uses Redis to store the counts of client requests. Redis is a key-value store, and each key used by this module is given a prefix to avoid collisions. You may specify your prefix here.

The prefix will default to the name of your application class if it isn't set explicitly, which should avoid collisions if you're running multiple applications on the same host.

exceeded

The run_mode to redirect the client to, when their request-count has exceeded the specified limit.

AUTHOR

Steve Kemp <steve@steve.org.uk>

COPYRIGHT AND LICENSE

Copyright (C) 2014 Steve Kemp <steve@steve.org.uk>.

This library is free software. You can modify and or distribute it under the same terms as Perl itself.