Plack-Middleware-Greylist
view release on metacpan or search on metacpan
lib/Plack/Middleware/Greylist.pm view on Meta::CPAN
package Plack::Middleware::Greylist;
# ABSTRACT: throttle requests with different rates based on net blocks
# RECOMMEND PREREQ: Cache::FastMmap 1.52
# RECOMMEND PREREQ: Ref::Util::XS
use v5.20;
use warnings;
use parent qw( Plack::Middleware );
use HTTP::Status qw/ HTTP_FORBIDDEN HTTP_TOO_MANY_REQUESTS /;
use List::Util 1.29 qw/ pairs /;
use Module::Load qw/ load /;
use Net::IP::LPM;
use Plack::Util;
use Plack::Util::Accessor qw/ default_rate rules cache file _match greylist retry_after cache_config callback /;
use Ref::Util qw/ is_plain_arrayref is_coderef /;
use Time::Seconds qw/ ONE_MINUTE /;
use experimental qw/ postderef signatures /;
our $VERSION = 'v0.8.1';
sub prepare_app($self) {
$self->default_rate(-1) unless defined $self->default_rate;
die "default_rate must be a positive integer" unless $self->default_rate =~ /^[1-9][0-9]*$/;
my $config = $self->cache_config;
$self->cache_config( $config //= {} ) unless defined $config;
$config->{init_file} //= 0;
$config->{unlink_on_exit} //= !$config->{init_file};
$config->{serializer} //= '';
my $expiry = $config->{expire_time} //= ONE_MINUTE;
$self->retry_after( $config->{expire_time} + 1 ) unless defined $self->retry_after;
die "retry_after must be a positive integer greater than $expiry seconds"
unless $self->retry_after =~ /^[1-9][0-9]*$/ && $self->retry_after > $expiry;
unless ( $self->cache ) {
my $file = $self->file // $config->{share_file};
die "No cache was set" unless defined $file;
$config->{share_file} = "$file";
load Cache::FastMmap;
die "Cache::FastMmap version 1.52 or newer is required" if Cache::FastMmap->VERSION < 1.52;
my $cache = Cache::FastMmap->new(%$config);
$self->cache(
sub($ip) {
return $cache->get_and_set(
$ip,
sub( $, $count, $opts ) {
$count //= 0;
return ( $count + 1, { expire_on => $opts->{expire_on} } );
}
);
}
);
}
my $match = Net::IP::LPM->new;
$self->_match( sub($ip) { $match->lookup($ip) } );
my @blocks;
if ( my $greylist = $self->greylist ) {
push @blocks, ( $greylist->%* );
}
( run in 1.218 second using v1.01-cache-2.11-cpan-5a3173703d6 )