Rate Limiting based on ACCESS TOKEN (OAuth 2.0)
Problem this snippet solves:
When publishing web services, you need to implement some rate limiting functions to avoid abuses. There are plenty of ways to setup Rate limiting
How to use this snippet:
The code below setup a rate limiting based on the ACCESS TOKEN. The client will receive a response "429 Too much requests" after 1000 requests in a window of 300 seconds.
The client can request its current status by doing a request to /rate_limit_status. He will then receive the following JSON message :
{ "x-rate-limit-limit": 1000, "x-rate-limit-remaining": 800, "x-rate-limit-reset": 100 }
Code :
when RULE_INIT {
###
# rate limit options
###
set static::request_limit 1000
set static::window_size 300
###
# define URI endpoints
###
set static::status_uri "/rate_limit_status"
}
when HTTP_REQUEST {
###
# initialize vars
###
set access_token ""
set client_ip ""
###
# retrieve the access_token. It will be used as a mandatory key to evaluate rate limiting
###
if { [HTTP::header exists Authorization] and [HTTP::header Authorization] contains "Bearer" } {
set access_token [getfield [HTTP::header Authorization] " " 2]
set client_ip [IP::client_addr]
}
if { !($access_token eq "") } {
###
# provide client with rate limit status
###
set key [sha1 $access_token]
set count [table lookup -notouch $key]
set time [table timeout -remaining $key]
###
# Provide a status page to the client
###
if { [HTTP::path] eq $static::status_uri and [HTTP::method] eq "GET" } {
if { $count > 0 } {
set x_rate_limit_limit "$static::request_limit"
set x_rate_limit_remaining "[expr {$static::request_limit-$count}]"
set x_rate_limit_reset "$time"
} else {
set x_rate_limit_limit "$static::request_limit"
set x_rate_limit_remaining "$static::request_limit"
set x_rate_limit_reset "$static::window_size"
}
HTTP::respond 200 content "{\"x-rate-limit-limit\": $x_rate_limit_limit,\"x-rate-limit-remaining\": $x_rate_limit_remaining,\"x-rate-limit-reset\": $x_rate_limit_reset}" noserver Content-Type "application/json" Connection Close
event disable all
} else {
###
# Handle the case where a client reach the rate limit
###
if { $count >= $static::request_limit } {
set x_rate_limit_limit "$static::request_limit"
set x_rate_limit_remaining "0"
set x_rate_limit_reset "$time"
HTTP::respond 429 content "{\"x-rate-limit-limit\": $x_rate_limit_limit,\"x-rate-limit-remaining\": $x_rate_limit_remaining,\"x-rate-limit-reset\": $x_rate_limit_reset}" noserver Content-Type "application/json" Connection Close
event disable all
} else {
if { $count == 0 } {
table add $key 1 $static::window_size $static::window_size
} else {
table incr -notouch $key
}
}
}
}
}Tested this on version:
11.5Updated Jun 06, 2023
Version 2.0Yann_Desmarest
Cirrus
Joined September 11, 2012
1 Comment
- Subrun
Cirrostratus
at version 14.1.0.6 is this already part of f5 or still we need to make a rule ?