PS: I’m using haproxy 3.0.8 on Debian.
I’m trying to make a configuration where a first counter is used to count the wall time taken by requests on a certain period, for this I store the start time of request then substract the time in after-response and add it to gpc0() and measure the rate with sc0_gpc0_rate. It works.
Next to that in after-response, if sc0_gpc0_rate is over a certain rate I increment gpc1 with sc-inc-gpc1(0), when showing gpc1 in a response header set during after-response, it works.
But know when I want to test gpc1 during http-request to deny a request if gpc1 > 0, here gpc1 is always 0.
My test configuration follow with my logs, you can see that the request-rate header transmitted to httpbin always contains 0, when the rate header on the response contains the gpc0 rate and the correct value for gpc1.
global
log stdout local0
stats socket /tmp/pytest-of-bdauvergne/pytest-417/test_request_limiting_by_durat0/stat.sock mode 600 level admin
defaults
log global
mode http
option httplog
timeout connect 60000
timeout client 60000
timeout server 60000
frontend httpbin
bind 127.0.0.128:8080
stick-table type ip size 100k expire 60s store gpc(2),gpc_rate(2,3s)
http-request set-header Request-Rate "%[src_get_gpc1]"
http-request set-var(txn.rate) src,table_gpc1
acl toomuch src,table_gpc1 gt 0
http-request track-sc0 src
http-request set-header Host httpbin.dev
http-request set-var(txn.start) date(0,ms)
http-request set-var(txn.duration) int(0)
http-request deny deny_status 429 content-type text/plain lf-string "coin" if toomuch
use_backend httpbin2
http-after-response set-var(txn.duration) date(0,ms),sub(txn.start)
http-after-response sc-add-gpc(0,0) var(txn.duration)
http-after-response sc-inc-gpc1(0) if { sc0_get_gpc0 gt 100 }
http-after-response set-header Timing "%[var(txn.duration)]"
http-after-response set-header Counter "%[sc0_get_gpc0]"
http-after-response set-var(txn.rate) src,table_gpc1
http-after-response set-header Rate "%[sc0_gpc0_rate] %[src_get_gpc1]"
backend httpbin2
server httpbin httpbin.dmuth.org:443 ssl verify none check-sni httpbin_domain sni str(httpbin.dmuth.org) maxconn 32
# table: httpbin, type: ip, size:102400, used:3
# table: httpbin, type: ip, size:102400, used:3
0x7fad35075320: key=127.0.0.2 use=0 exp=59923 shard=0 gpc0=431 gpc1=3 gpc0_rate(3000)=431 gpc1_rate(3000)=3
0x7fad44bc2660: key=127.0.0.3 use=0 exp=59924 shard=0 gpc0=430 gpc1=3 gpc0_rate(3000)=430 gpc1_rate(3000)=3
0x7fad44e76320: key=127.0.0.1 use=0 exp=59990 shard=0 gpc0=641 gpc1=4 gpc0_rate(3000)=641 gpc1_rate(3000)=4
Last logs:
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.1:57155 [19/Mar/2025:10:16:41.143] httpbin httpbin2/httpbin 0/0/48/94/142 200 857 - - ---- 10/10/9/9/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.3:39927 [19/Mar/2025:10:16:41.144] httpbin httpbin2/httpbin 0/0/45/97/143 200 857 - - ---- 10/10/8/8/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.2:57767 [19/Mar/2025:10:16:41.145] httpbin httpbin2/httpbin 0/0/46/95/143 200 857 - - ---- 10/10/6/6/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.1:42511 [19/Mar/2025:10:16:41.144] httpbin httpbin2/httpbin 0/0/45/99/144 200 857 - - ---- 10/10/6/6/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.3:51671 [19/Mar/2025:10:16:41.146] httpbin httpbin2/httpbin 0/0/45/97/142 200 857 - - ---- 10/10/5/5/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.2:33375 [19/Mar/2025:10:16:41.144] httpbin httpbin2/httpbin 0/0/46/99/145 200 857 - - ---- 10/10/4/4/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.1:52105 [19/Mar/2025:10:16:41.145] httpbin httpbin2/httpbin 0/0/45/99/145 200 857 - - ---- 9/9/3/3/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.2:39745 [19/Mar/2025:10:16:41.144] httpbin httpbin2/httpbin 0/0/48/98/147 200 857 - - ---- 9/9/2/2/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.3:51557 [19/Mar/2025:10:16:41.144] httpbin httpbin2/httpbin 0/0/47/99/146 200 857 - - ---- 9/9/1/1/0 0/0 "GET /headers HTTP/1.1"
<134>Mar 19 10:16:41 haproxy[2321424]: 127.0.0.1:55829 [19/Mar/2025:10:16:41.146] httpbin httpbin2/httpbin 0/0/46/165/211 200 857 - - ---- 1/1/0/0/0 0/0 "GET /headers HTTP/1.1"
defaultdict(<class 'set'>,
{200: {(0,
'127.0.0.1',
'Request-Rate: 0',
'Timing: 142',
'Counter: 142',
'Rate: 142 1'),
(1,
'127.0.0.2',
'Request-Rate: 0',
'Timing: 145',
'Counter: 431',
'Rate: 431 3'),
(2,
'127.0.0.3',
'Request-Rate: 0',
'Timing: 141',
'Counter: 141',
'Rate: 141 1'),
(3,
'127.0.0.1',
'Request-Rate: 0',
'Timing: 144',
'Counter: 430',
'Rate: 430 3'),
(4,
'127.0.0.2',
'Request-Rate: 0',
'Timing: 145',
'Counter: 286',
'Rate: 431 3'),
(5,
'127.0.0.3',
'Request-Rate: 0',
'Timing: 146',
'Counter: 430',
'Rate: 430 3'),
(6,
'127.0.0.1',
'Request-Rate: 0',
'Timing: 144',
'Counter: 286',
'Rate: 286 2'),
(7,
'127.0.0.2',
'Request-Rate: 0',
'Timing: 141',
'Counter: 141',
'Rate: 141 1'),
(8,
'127.0.0.3',
'Request-Rate: 0',
'Timing: 143',
'Counter: 284',
'Rate: 284 2'),
(9,
'127.0.0.1',
'Request-Rate: 0',
'Timing: 211',
'Counter: 641',
'Rate: 641 4')}})
1 post - 1 participant