Skip to content

Instantly share code, notes, and snippets.

@bpinto
Last active June 10, 2022 13:29
Show Gist options
  • Save bpinto/28a72f11a3327cee8a07ab5956408ce4 to your computer and use it in GitHub Desktop.
Save bpinto/28a72f11a3327cee8a07ab5956408ce4 to your computer and use it in GitHub Desktop.
haproxy throttling
HTTP/1.1 429 Too Many Requests
Cache-Control: no-cache
Connection: close
Content-Type: text/html
Retry-After: 60
<html><body><h1>429 Too Many Requests</h1>
Too many requests
</body></html>
global
daemon
pidfile /var/run/haproxy.pid
# Settings in the defaults section apply to all services (unless you change it,
# this configuration defines one service, called rails).
defaults
log global
mode http
maxconn 65535
option httplog
retries 3
timeout client 1s
timeout connect 1s
timeout server 1s
frontend in
bind *:80
default_backend app
tcp-request inspect-delay 5s
acl too_many_api_requests sc0_gpc0_rate gt 2
acl mark_seen sc0_inc_gpc0 gt 0
stick-table type string size 200k store gpc0_rate(10s)
tcp-request content track-sc0 hdr(Authorization)
use_backend rate_limit if too_many_api_requests || !mark_seen
use_backend rate_limit if too_many_api_requests
backend app
server perlapp 127.0.0.1:8080
backend rate_limit
timeout tarpit 20s
errorfile 500 /src/429.http
http-request tarpit
Running requests
Throttling: Max of 2 requests in 10 seconds
First request, 200 - OK
Second request, 200 - OK
Third request, 429 - OK
Sleeping for 5 seconds
Fourth request, 429 - OK
Sleeping for 6 seconds (6+5 > 10s)
Unexpected error:
<html><body><h1>429 Too Many Requests</h1> Too many requests </body></html>
Sleeping for 11 seconds
Sixth request, 200 - OK
#!/bin/bash
echo 'Installing dependencies'
apt-get -qq update -y
apt-get -qq install -y curl libtest-http-server-simple-perl > /dev/null
echo 'Starting server'
perl -MHTTP::Server::Simple -e '$s = HTTP::Server::Simple->new(); $s->run' &
sleep 2
echo 'Starting haproxy'
haproxy -f /src/haproxy.cfg
echo "\nRunning requests"
echo 'Throttling: Max of 2 requests in 10 seconds'
OUTPUT=$(curl -v --silent http://user:password@localhost/ 2>/dev/null)
if echo "$OUTPUT" | grep -q Congratulations; then
echo 'First request, 200 - OK'
else
echo 'First request, FAIL:'
echo $OUTPUT
fi
OUTPUT=$(curl -v --silent http://user:password@localhost/ 2>/dev/null)
if echo "$OUTPUT" | grep -q Congratulations; then
echo 'Second request, 200 - OK'
else
echo 'Unexpected error:'
echo $OUTPUT
fi
OUTPUT=$(curl -v --silent http://user:password@localhost/ 2>/dev/null)
if echo "$OUTPUT" | grep -q 429; then
echo 'Third request, 429 - OK'
else
echo 'Unexpected error:'
echo $OUTPUT
fi
OUTPUT=$(curl -v --silent http://user:NEW_PASSWORD@localhost/ 2>/dev/null)
if echo "$OUTPUT" | grep -q Congratulations; then
echo 'Different credential, 200 - OK'
else
echo 'Unexpected error:'
echo $OUTPUT
fi
echo 'Sleeping for 5 seconds'
sleep 5
OUTPUT=$(curl -v --silent http://user:password@localhost/ 2>/dev/null)
if echo "$OUTPUT" | grep -q 429; then
echo 'Fourth request, 429 - OK'
else
echo 'Unexpected error:'
echo $OUTPUT
fi
echo 'Sleeping for 6 seconds (6+5 > 10s)'
sleep 6
OUTPUT=$(curl -v --silent http://user:password@localhost/ 2>/dev/null)
if echo "$OUTPUT" | grep -q Congratulations; then
echo 'Fifth request, 200 - OK'
else
echo 'Unexpected error:'
echo $OUTPUT
fi
echo 'Sleeping for 11 seconds'
sleep 11
OUTPUT=$(curl -v --silent http://user:password@localhost/ 2>/dev/null)
if echo "$OUTPUT" | grep -q Congratulations; then
echo 'Sixth request, 200 - OK'
else
echo 'Unexpected error:'
echo $OUTPUT
fi
kill $(cat /var/run/haproxy.pid)
@jmagnin
Copy link

jmagnin commented Mar 29, 2018

frontend fe_rlimit
mode http
bind *:8000
acl toomany sc0_http_req_rate gt 2
stick-table type string size 20 store http_req_rate(10s)
tcp-request content track-sc0 src
use_backend be_limit if toomany
default_backend be_app

backend be_limit
http-request tarpit
timeout tarpit 2
errorfile 500 /path/to/file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment