The login/logout feature on FastAPI works in the browser, but I am trying to write unit tests for it. When my app sets the cookie, I can see the response DOES have the cookie sent. When I receive it with Python Request, the cookie has been stripped from the response hence the login doesn't work.
@pytest.fixture(scope='module')
def test_client():
app = create_app(testing=True)
client = TestClient(app)
client.base_url = 'https://localhost'
from app.models import Base, User
Base.metadata.create_all(bind=engine)
yield client
db.flush()
Base.metadata.drop_all(bind=engine)
# Simple login functions.
def test_login(test_client):
response = test_client.post(url='/login', data=dict(
username=username,
password=password
), allow_redirects=True, proxies=proxies)
breakpointB()
assert response.headers
Then the server side which works in the browser:
@core.post("/login", response_model=schemas.Token)
async def login_for_access_token(*, request: Request, form_data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(get_db)):
token = jsonable_encoder(access_token)
response = RedirectResponse(url=request.url_for('index'), status_code=303)
response.set_cookie(
"Authorization",
value=f"Bearer {token}",
domain=os.environ.get('DOMAIN'),
httponly=False,
max_age=1800,
expires=1800,
)
breakpointA()
return response
So at BreakpointA(), just before the response is sent, this is what response.headers looks like:
MutableHeaders({'location': 'https://localhost/', 'set-cookie': 'Authorization="Bearer e
yJ0eXAiO5JKV1iLCJ4bGciOiJ2UzI1NiJ9.eyJzdWIiOi2b2Vqb2UiL253JleH1iOjE1DM0ODEzNTR7.zwbT9yV
OnV2V14Yrtuc1PP8wv82alz2354sgm0Rc7PgZIvc"; Domain=https://localhost; expires=Fri, 06 Mar 202
0 07:55:54 GMT; Max-Age=1800; Path=/'})
At BreakpointB(), on my test client side AFTER the response has been recieved, this is what response.headers and response.cookies looks like:
(Pdb) response.headers
{'content-length': '24956', 'content-type': 'text/html; charset=utf-8'}
(Pdb) response.cookies
<RequestsCookieJar[]>
(Pdb) response.cookies.get_dict()
{}
I have a strong suspicion this is because of the domain issue - but how do I correct for this? In my TestClient (Starlette TestClient), I have set client.base_url = 'https://localhost', and in my endpoint when making the cookie I've set DOMAIN=https://localhost. Anyone have any experience fixing this?
I experienced the same issue. While not a perfect solution, I ended up doing this in my test:
assert "Authorization" in response.headers['set-cookie']
...you could check for more things in the string as needed.
Just ran into this issue, in my case, it is indeed because of the cookie domain used in TestClient.
You can supply your cookie_domain as the base_url to your TestClient:
client = TestClient(app, base_url="http://example.com")
set-cookie should work as long as the base_url is consistent with the cookie domain.
Edit: make sure your cookie domain is an FQDN without http:// or https:// prefixes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With