Files
juwan-backend/deploy/dev/script/test-ratelimit.py
2026-04-06 12:29:48 +08:00

84 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""测试 Envoy 限流是否生效"""
import http.client
import json
import re
BASE = "127.0.0.1"
PORT = 18080
ENDPOINTS = [
(
"/api/v1/auth/login",
10,
{"username": "test", "password": "test", "phone": "0", "remember": True},
),
(
"/api/v1/auth/register",
5,
{"username": "test", "password": "test", "phone": "0"},
),
("/api/v1/auth/forgot-password/send", 3, {"email": "test@test.com"}),
("/api/v1/email/verification-code/send", 3, {"email": "test@test.com"}),
]
def get_cookies():
conn = http.client.HTTPConnection(BASE, PORT)
conn.request("GET", "/healthz")
resp = conn.getresponse()
resp.read()
cookies = {}
for h, v in resp.getheaders():
if h.lower() == "set-cookie":
m = re.match(r"([^=]+)=([^;]+)", v)
if m:
cookies[m.group(1)] = m.group(2)
conn.close()
return cookies
def post(cookies, path, body_dict):
conn = http.client.HTTPConnection(BASE, PORT)
token = cookies.get("__Host-XSRF-TOKEN", "")
guard = cookies.get("__Host-XSRF-GUARD", "")
headers = {
"Content-Type": "application/json",
"Cookie": f"__Host-XSRF-TOKEN={token}; __Host-XSRF-GUARD={guard}",
"xsrf-token": token,
}
conn.request("POST", path, body=json.dumps(body_dict), headers=headers)
resp = conn.getresponse()
resp.read()
rl_remain = resp.getheader("x-ratelimit-remaining", "-")
ratelimited = resp.getheader("x-envoy-ratelimited", "")
conn.close()
return resp.status, rl_remain, bool(ratelimited)
def test_endpoint(cookies, path, limit, body_dict):
count = limit + 3
print(f"\n=== {path} (限额 {limit}/min, 发 {count} 次) ===")
first_429 = None
for i in range(1, count + 1):
status, remain, limited = post(cookies, path, body_dict)
tag = " ← 429!" if limited else ""
print(f" #{i:02d} status={status} remaining={remain}{tag}")
if limited and first_429 is None:
first_429 = i
if first_429 == limit + 1:
print(f" ✓ 第 {first_429} 次触发限流,符合预期")
elif first_429:
print(f" ✗ 第 {first_429} 次触发限流,预期第 {limit + 1}")
else:
print(f" ✗ 未触发限流!")
print("获取 CSRF Cookie...")
cookies = get_cookies()
print(f" token = {cookies.get('__Host-XSRF-TOKEN', '?')[:40]}...")
for path, limit, body in ENDPOINTS:
test_endpoint(cookies, path, limit, body)