summary refs log tree commit diff
diff options
context:
space:
mode:
authorfranck cuny <franck@lumberjaph.net>2010-04-27 18:47:49 +0200
committerfranck cuny <franck@lumberjaph.net>2010-04-27 18:47:49 +0200
commit2ae3fd059b5aaf093c7fb26e674833b65008ad42 (patch)
treec62d4d46851bfff1db49a734e1fb315d90ce2e40
parenttests (diff)
downloadplack-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.pm22
-rw-r--r--t/05_filter_path.t10
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';
     }
 };