import devplacepy.main as m from starlette.testclient import TestClient def _patch_limits(monkeypatch, limit, window=60): def fake_get_int_setting(key, default): return {"rate_limit_per_minute": limit, "rate_limit_window_seconds": window}.get(key, default) monkeypatch.setattr(m, "get_int_setting", fake_get_int_setting) m._rate_limit_store.clear() def test_rate_limit_blocks_excess(monkeypatch): _patch_limits(monkeypatch, 3) client = TestClient(m.app) codes = [client.post("/", headers={"X-Real-IP": "9.9.9.9"}).status_code for _ in range(6)] assert 429 in codes, codes assert codes[-1] == 429 def test_rate_limit_is_per_ip(monkeypatch): _patch_limits(monkeypatch, 2) client = TestClient(m.app) for _ in range(2): client.post("/", headers={"X-Real-IP": "1.1.1.1"}) blocked = client.post("/", headers={"X-Real-IP": "1.1.1.1"}).status_code other_ip = client.post("/", headers={"X-Real-IP": "2.2.2.2"}).status_code assert blocked == 429 assert other_ip != 429 def test_get_requests_not_rate_limited(monkeypatch): _patch_limits(monkeypatch, 2) client = TestClient(m.app) codes = [client.get("/robots.txt", headers={"X-Real-IP": "3.3.3.3"}).status_code for _ in range(5)] assert all(c == 200 for c in codes), codes def test_rate_limit_reads_configured_setting(monkeypatch): _patch_limits(monkeypatch, 1) client = TestClient(m.app) first = client.post("/", headers={"X-Real-IP": "7.7.7.7"}).status_code second = client.post("/", headers={"X-Real-IP": "7.7.7.7"}).status_code assert first != 429 assert second == 429