Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
ensembl-rest
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Iterations
Wiki
Requirements
Jira
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
ensembl-gh-mirror
ensembl-rest
Commits
301b0797
Commit
301b0797
authored
9 years ago
by
Magali Ruffier
Browse files
Options
Downloads
Plain Diff
Merge pull request #92 from Ensembl/
ENSCORESW-1551
Enscoresw 1551
parents
db8be604
63ce9e72
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
lib/Plack/Middleware/EnsThrottle.pm
+35
-1
35 additions, 1 deletion
lib/Plack/Middleware/EnsThrottle.pm
t/ratelimit.t
+23
-0
23 additions, 0 deletions
t/ratelimit.t
with
58 additions
and
1 deletion
lib/Plack/Middleware/EnsThrottle.pm
+
35
−
1
View file @
301b0797
...
...
@@ -45,6 +45,8 @@ enable 'EnsThrottle::Second',
},
blacklist => '192.168.2.1', #blacklist a single IP
whitelist => ['192.168.0.0-192.169.255.255'], #whitelist a range
whitelist_hdr => 'X-My-Secret-Token',
whitelist_hdr_values => ['loveme'],
client_id_prefix => 'second', #make the generated key more unique
message => 'custom rate exceeded message',
# If specified once limit has been hit add this value to the Retry-After header.
...
...
@@ -100,12 +102,13 @@ In all cases they limit up-to their time unit. For example a user is first seen
use
strict
;
use
warnings
;
use
parent
'
Plack::Middleware
';
use
Plack::Util::
Accessor
qw(max_requests backend path blacklist whitelist client_id_prefix message retry_after_addition)
;
use
Plack::Util::
Accessor
qw(max_requests backend path blacklist whitelist
whitelist_hdr whitelist_hdr_values
client_id_prefix message retry_after_addition)
;
use
Plack::
Util
;
use
Carp
;
use
Net::CIDR::
Lite
;
use
Readonly
;
use
Plack::Middleware::EnsThrottle::
SimpleBackend
;
use
Plack::
Request
;
Readonly::
Scalar
my
$CLIENT_ID_PREFIX
=>
'
throttle
';
Readonly::
Scalar
my
$MESSAGE
=>
'
Too many requests
';
...
...
@@ -125,6 +128,7 @@ sub prepare_app {
croak
"
Cannot continue. No max_requests given
"
unless
$self
->
max_requests
();
$self
->
blacklist
(
$self
->
_populate_cidr
(
$self
->
blacklist
));
$self
->
whitelist
(
$self
->
_populate_cidr
(
$self
->
whitelist
));
$self
->
whitelist_hdr_values
(
$self
->
_populate_array
(
$self
->
whitelist_hdr_values
));
my
$path
=
$self
->
path
();
croak
"
Cannot continue. No path given
"
unless
$path
;
croak
"
Cannot continue. path must be an CODE ref
"
if
ref
(
$path
)
ne
'
CODE
';
...
...
@@ -139,6 +143,8 @@ sub call {
my
$res
;
my
$remaining_requests
=
0
;
my
$request
=
Plack::
Request
->
new
(
$env
);
if
(
$self
->
_throttle_path
(
$env
))
{
#If IP was in the blacklist then reject & allow no headers
...
...
@@ -151,6 +157,10 @@ sub call {
$res
=
$self
->
app
->
(
$env
);
$add_headers
=
0
;
}
elsif
(
$self
->
_whitelisted_hdr
(
$request
->
headers
))
{
$res
=
$self
->
app
->
(
$env
);
$add_headers
=
0
;
}
else
{
$remaining_requests
=
$self
->
remaining_requests
(
$env
);
#If we are throttled then we have to prepare the throttle response
...
...
@@ -270,6 +280,20 @@ sub _whitelisted {
return
$list
->
find
(
$env
->
{
REMOTE_ADDR
});
}
sub
_whitelisted_hdr
{
my
(
$self
,
$headers
)
=
@_
;
my
$header
=
$self
->
whitelist_hdr
();
my
$values
=
$self
->
whitelist_hdr_values
();
return
0
unless
$header
&&
@
{
$values
};
# Since this is a special header just for us we're
# going to assume there's only one value, to speed
# the checking code below
my
$hdr_value
=
$headers
->
header
(
$header
);
return
0
unless
$hdr_value
;
return
grep
{
$_
eq
$hdr_value
}
@
{
$values
};
}
sub
_client_id
{
my
(
$self
,
$env
)
=
@_
;
my
$id
;
...
...
@@ -293,4 +317,14 @@ sub _populate_cidr {
return
$cidr
;
}
# Ensure value is an array if a scalar is passed
sub
_populate_array
{
my
(
$self
,
$input
)
=
@_
;
if
(
$input
)
{
$input
=
(
ref
(
$input
)
eq
'
ARRAY
')
?
$input
:
[
$input
];
}
return
$input
;
}
1
;
This diff is collapsed.
Click to expand it.
t/ratelimit.t
+
23
−
0
View file @
301b0797
...
...
@@ -85,6 +85,8 @@ assert_basic_rate_limit('EnsThrottle::Second', 1, 'second', 'You have done too m
max_requests
=>
1
,
whitelist
=>
'
192.168.2.1
',
blacklist
=>
['
192.167.0.0-192.167.255.255
'],
whitelist_hdr
=>
'
Token
',
whitelist_hdr_values
=>
['
loveme
',
'
imacool
'],
client_id_prefix
=>
'
second
',
backend
=>
Plack::Middleware::EnsThrottle::
SimpleBackend
->
new
();
sub
{
...
...
@@ -122,6 +124,27 @@ assert_basic_rate_limit('EnsThrottle::Second', 1, 'second', 'You have done too m
is
(
$res
->
code
(),
200
,
'
Checking for a 200
');
cmp_ok
(
$res
->
header
('
X-RateLimit-Remaining
'),
'
==
',
0
,
'
Remaining header is 0
');
note
'
Checking if rate limit is disabled using magic password headers
';
$res
=
$cb
->
(
GET
'
/
',
'
Token
'
=>
'
imacool
');
is
(
$res
->
code
(),
200
,
'
Checking for a 200
');
note
'
Sending request again with the rate limit disabling header
';
$res
=
$cb
->
(
GET
'
/
',
'
Token
'
=>
'
imacool
');
is
(
$res
->
code
(),
200
,
'
Checking for a 200
');
note
'
And pause then try with the wrong token value
';
sleep
(
1
);
$res
=
$cb
->
(
GET
'
/
');
is
(
$res
->
code
(),
200
,
'
Checking for a 200
');
$res
=
$cb
->
(
GET
'
/
',
'
Token
'
=>
'
imnocool
');
is
(
$res
->
code
(),
429
,
'
Checking for a 429
');
note
'
And pause then try with the wrong token header
';
sleep
(
1
);
$res
=
$cb
->
(
GET
'
/
');
is
(
$res
->
code
(),
200
,
'
Checking for a 200
');
$res
=
$cb
->
(
GET
'
/
',
'
Ttoken
'
=>
'
imacool
');
is
(
$res
->
code
(),
429
,
'
Checking for a 429
');
note
'
Checking an ignored non-rate limited path
';
$res
=
$cb
->
(
GET
'
/ignore
');
is
(
$res
->
code
(),
200
,
'
Checking for a 200 on the non-throttled path
');
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment