Open Miguelme opened 1 year ago
Also looking forward to a solution ... how are we supposed to test our endpoints when rate-limiting is active?
In my case, I have the following test-file:
from fastapi.testclient import TestClient
from app.misc import normalize_phone_number
from app.database.models.user import User
from app.misc import get_db
from app.services.otp import store_otp_for_user
from app.main import app
client = TestClient(app)
def test_register_new_user(clear_database):
clear_database()
phone_number = "+4915202551672"
response = client.post(
"/users/register",
json={
"name": "Test User",
"phone_number": phone_number
}
)
assert response.status_code == 201
assert response.json()["id"] == 1
assert response.json()["name"] == "Test User"
assert response.json()["phone_number"] == normalize_phone_number(phone_number)
assert response.json()["verified"] == False
# get the user from the db
session = next(get_db())
user = session.query(User).filter(User.id == 1).first()
assert len(user.otps) == 1
Using pytest for testing, results in the following error:
FAILED tests/test_user_registration.py::test_register_new_user - Exception: You must call FastAPILimiter.init in startup event of fastapi!
As far as I know, the startup
event is not being called by the TestClient
?
I have managed to do so by modifying the RateLimiter
class:
class CustomRateLimiter(RateLimiter):
def __hash__(self) -> int:
return hash(f"limiter-{hash(self.CUSTOM_ID_VALUE)}")
def __eq__(self, other: object) -> bool:
if isinstance(other, CustomRateLimiter):
return self.CUSTOM_ID_VALUE == other.CUSTOM_ID_VALUE
return False
Then use app.dependency_overrides[CustomRateLimiter(xxx)] = lambda: True
, where xxx is the exact same setting as in the endpoint for which you want to override the RateLimiter dependency (in the case of lambda: True
it basically disables the rate limit).
Source: https://github.com/tiangolo/fastapi/issues/2795#issuecomment-819476279
I have managed to do so by modifying the
RateLimiter
class:class CustomRateLimiter(RateLimiter): def __hash__(self) -> int: return hash(f"limiter-{hash(self.CUSTOM_ID_VALUE)}") def __eq__(self, other: object) -> bool: if isinstance(other, CustomRateLimiter): return self.CUSTOM_ID_VALUE == other.CUSTOM_ID_VALUE return False
Then use
app.dependency_overrides[CustomRateLimiter(xxx)] = lambda: True
, where xxx is the exact same setting as in the endpoint for which you want to override the RateLimiter dependency (in the case oflambda: True
it basically disables the rate limit).Source: fastapi/fastapi#2795 (comment)
FIxes pytest issues, but for my implementation, where I've seperated GET and PUT,etc., rate limit values, my fastapi app applies the GET timer to non-GET endpoints. Some overlap in the hash by redis or something.
What is the expected way of overriding the dependency for the rate limiter from the tests? Any example would be appreciated