diff options
author | franck cuny <franck@lumberjaph.net> | 2010-04-27 18:47:49 +0200 |
---|---|---|
committer | franck cuny <franck@lumberjaph.net> | 2010-04-27 18:47:49 +0200 |
commit | 2ae3fd059b5aaf093c7fb26e674833b65008ad42 (patch) | |
tree | c62d4d46851bfff1db49a734e1fb315d90ce2e40 | |
parent | tests (diff) | |
download | plack-middleware-throttle-2ae3fd059b5aaf093c7fb26e674833b65008ad42.tar.gz |
change how path works, by default the whole application is throttled, but if path is specified, only this path will be throttled
-rw-r--r-- | lib/Plack/Middleware/Throttle.pm | 22 | ||||
-rw-r--r-- | t/05_filter_path.t | 10 |
2 files changed, 19 insertions, 13 deletions
diff --git a/lib/Plack/Middleware/Throttle.pm b/lib/Plack/Middleware/Throttle.pm index 3ef72a9..25b2aad 100644 --- a/lib/Plack/Middleware/Throttle.pm +++ b/lib/Plack/Middleware/Throttle.pm @@ -21,7 +21,7 @@ has white_list => ( is => 'rw', isa => 'ArrayRef', predicate => 'has_white_list' ); has black_list => ( is => 'rw', isa => 'ArrayRef', predicate => 'has_black_list' ); -has path => ( is => 'rw', isa => 'ArrayRef', predicate => 'has_path' ); +has path => ( is => 'rw', isa => 'RegexpRef', predicate => 'has_path' ); sub prepare_app { my $self = shift; @@ -45,8 +45,9 @@ sub call { my $res = $self->app->($env); - return $res if $self->path_is_not_throttled($env); - return $res if $self->is_white_listed($env); + return $res unless $self->path_is_throttled($env); + + return $res if $self->is_white_listed($env); return $self->forbiden if $self->is_black_listed($env); my $key = $self->cache_key($env); @@ -94,12 +95,16 @@ sub is_black_listed { return 0; } -sub path_is_not_throttled { +sub path_is_throttled { my ( $self, $env ) = @_; + return 0 if !$self->has_path; + my $path_match = $self->path; my $path = $env->{PATH_INFO}; - if ( grep { $path =~ /$_/ } @{ $self->path } ) { - return 1; + + for ($path) { + my $matched = 'CODE' eq ref $path_match ? $path_match->($_) : $_ =~ $path_match; + $matched ? return 1 : return 0; } return 0; } @@ -155,7 +160,8 @@ Plack::Middleware::Throttle - A Plack Middleware for rate-limiting incoming HTTP my $handler = builder { enable "Throttle::Hourly", max => 2, - backend => Plack::Middleware::Throttle::Backend::Hash->new(); + backend => Plack::Middleware::Throttle::Backend::Hash->new(), + path => qr{^/foo}; sub { [ '200', [ 'Content-Type' => 'text/html' ], ['hello world'] ] }; }; @@ -212,7 +218,7 @@ Key to prefix sessions entry in the cache. =item B<path> -List of regex for path exclusions. +URL pattern or a callback to match request to throttle. If no path is specified, the whole application will be throttled. =item B<white_list> diff --git a/t/05_filter_path.t b/t/05_filter_path.t index 73ec24b..1be3706 100644 --- a/t/05_filter_path.t +++ b/t/05_filter_path.t @@ -11,7 +11,7 @@ my $handler = builder { enable "Throttle::Hourly", max => 1, backend => Plack::Middleware::Throttle::Backend::Hash->new(), - path => [qr/^\/foo/]; + path => qr{^/foo}; sub { [ '200', [ 'Content-Type' => 'text/html' ], ['hello world'] ] }; }; @@ -21,17 +21,17 @@ test_psgi my $cb = shift; { for ( 1 .. 2 ) { - my $req = GET "http://localhost/foo"; + my $req = GET "http://localhost/bar"; my $res = $cb->($req); is $res->content, 'hello world', 'content is valid'; ok !$res->header('X-RateLimit-Limit'), 'no header ratelimit'; } - my $req = GET "http://localhost/bar"; + my $req = GET "http://localhost/foo"; my $res = $cb->($req); is $res->content, 'hello world', 'content is valid'; ok $res->header('X-RateLimit-Limit'), 'header ratelimit'; - my $req = GET "http://localhost/bar"; - my $res = $cb->($req); + $req = GET "http://localhost/foo"; + $res = $cb->($req); is $res->code, 503, 'rate limit exceeded'; } }; |