use strict; use warnings; use Test::More; use Plack::Test; use Plack::Builder; use HTTP::Request::Common; use Redis; my $default_server = $ENV{REDIS_SERVER} || '127.0.0.1:6379'; my $redis = eval { Redis->new(server => $default_server, debug => 0) }; plan skip_all => "Redis-server needs to be running on '$default_server' for tests" unless $redis; $redis->select(0); $redis->flushdb; # simple application my $app = sub { [200, [ 'Content-Type' => 'text/html' ], [ 'OK' ]] }; # fixed REMOTE_USER bundle my $appx = sub { my ($limits) = @_; builder { enable 'Throttle::Lite', limits => $limits, routes => '/api/user', backend => [ 'Redis' => { instance => $default_server } ]; $app; }; }; # faked REMOTE_USER bundle my $appy = sub { my ($user) = @_; builder { enable sub { my ($app) = @_; sub { my ($env) = @_; $env->{REMOTE_USER} = $user; $app->($env); }; }; $appx->('5 req/hour'); }; }; my @samples = ( # code used expire content mime 1, 200, 1, '', 'OK', 'text/html', 2, 200, 2, '', 'OK', 'text/html', 3, 200, 3, '', 'OK', 'text/html', 4, 200, 4, '', 'OK', 'text/html', 5, 200, 5, '1', 'OK', 'text/html', 6, 429, 5, '1', 'Limit Exceeded', 'text/plain', 7, 429, 5, '1', 'Limit Exceeded', 'text/plain', ); my $checks = sub { my ($cb, $key, $samples) = @_; while (my ($num, $code, $used, $expire_in, $content, $type) = splice(@$samples, 0, 6)) { my $reqno = 'Request (' . $num . ') [' . $key . ']'; my $res = $cb->(GET '/api/user/login'); is $res->code, $code, $reqno . ' code'; is $res->header('X-Throttle-Lite-Used'), $used, $reqno . ' used header'; is defined($res->header('X-Throttle-Lite-Expire')), $expire_in, $reqno . ' expire-in header'; is defined($res->header('Retry-After')), $expire_in, $reqno . ' retry-after header'; like $res->content, qr/$content/, $reqno . ' content'; is $res->content_type, $type, $reqno . ' content type'; } }; # username fixed to 'nobody', limits - vary my @limits = ('5 req/hour', '5 req/day'); my %by_limits = map { $_ => [ @samples ] } @limits; test_psgi $appx->($_), sub { my ($cb) = @_; $checks->($cb, $_, $by_limits{$_}) } for @limits; # limits fixed to '5 req/hour', users - vary my @users = qw(Tom Dick Harry); my %by_users = map { $_ => [ @samples ] } @users; test_psgi $appy->($_), sub { my ($cb) = @_; $checks->($cb, $_, $by_users{$_}) } for @users; done_testing();