""" Rate limits are per client, not per proxy. meshbay.org's hub sits behind Caddy on the same host, so every request's TCP peer is loopback. The limiter was keyed on that peer (slowapi's get_remote_address) while `client_ip` -- written "for the audit log and rate limiting" -- went unused by it, so each limit was one bucket for the whole internet: ten node sign-ins a minute shared by every node. A node that started while others signed in got 429, sat in `waiting_for_hub`, and the desktop app took that for no node at all. Every other test runs with the limiter disabled, which is how it hid. """ import pytest from meshbay_hub.api.middleware import limiter from meshbay_hub.api.netutil import client_ip @pytest.fixture def limits_on(): limiter.reset() limiter.enabled = True yield limiter.enabled = False limiter.reset() def _auth(client, ip): # The ASGI test transport's peer is 127.0.0.1 -- a trusted proxy, as Caddy is. return client.post("/v1/nodes/auth", json={"username": "nobody", "timestamp": 0, "signature": "AAAA"}, headers={"X-Forwarded-For": ip}) async def test_one_client_is_limited(client, limits_on): for _ in range(10): assert (await _auth(client, "203.0.113.1")).status_code != 429 assert (await _auth(client, "203.0.113.1")).status_code == 429 async def test_another_client_behind_the_same_proxy_is_not(client, limits_on): for _ in range(11): await _auth(client, "203.0.113.1") assert (await _auth(client, "203.0.113.2")).status_code != 429, ( "a second client behind the proxy shared the first one's bucket") def test_the_limiter_resolves_clients_the_way_the_audit_log_does(): assert limiter._key_func is client_ip