feat(tunnel): free finished tunnels at once and wait out 429s on --remote

A tunnel closed with code 1000 is freed without the 60s grace, a shared: true API key counts tunnels per X-Client-Id, and --remote waits out Retry-After and a full tunnel cap with a countdown; responses carry X-RateLimit-* headers.
This commit is contained in:
imSp4rky
2026-11-09 15:43:33 -07:00
parent 4b6d15cc2a
commit b10fd2d3a4
13 changed files with 358 additions and 25 deletions
+5 -1
View File
@@ -252,9 +252,13 @@ async def test_rate_limited_request_returns_429(aiohttp_client, monkeypatch) ->
setup_routes(app, remote_only=True, dashboard=True)
client = await aiohttp_client(app)
assert (await client.get("/api/services", headers={"X-Secret-Key": "tier-key"})).status == 200
resp = await client.get("/api/services", headers={"X-Secret-Key": "tier-key"})
assert resp.status == 200
assert (resp.headers["X-RateLimit-Limit"], resp.headers["X-RateLimit-Remaining"]) == ("1", "0")
assert 0 < int(resp.headers["X-RateLimit-Reset"]) <= 3600
resp = await client.get("/api/services", headers={"X-Secret-Key": "tier-key"})
assert resp.status == 429 and int(resp.headers["Retry-After"]) > 0
assert resp.headers["X-RateLimit-Remaining"] == "0"
assert (await client.get("/api/health", headers={"X-Secret-Key": "tier-key"})).status == 200
assert (await client.get("/api/health")).status == 401
# The dashboard key leaves the middleware before the limit check, so it always answers.