You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a 302 sets or clears a cookie, newer versions of aiohttp do not correctly process this.
Expected behaviour
If a 302 response sets a cookie, the resulting request will use the new value.
If a 302 response clears a cookie, the resulting request will omit that cookie.
Actual behaviour
In aiohttp 3.4.4:
As expected.
As expected.
In aiohttp 3.5.0:
If a 302 sets a cookie, the old value remains.
As expected.
In aiohttp 3.5.3:
If a 302 sets a cookie, the old value remains.
If a 302 clears a cookie, the old value remains.
Steps to reproduce
importloggingimportpytestimportsocketimportsysfromaiohttpimportClientSession, log, web@pytest.mark.asyncioasyncdeftest_302_cookie(host_and_session):
""" Baseline: check that /200 returns the content of the cookie set by the client """host, session=host_and_sessionasyncwithsession.get(host+'/200') asresponse:
assertawaitresponse.text() ==''assertresponse.cookies.get('c').value=='something'asyncwithsession.get(host+'/200') asresponse:
assertawaitresponse.text() =='something'assertresponse.cookies.get('c').value=='something'@pytest.mark.asyncioasyncdeftest_302_cookie(host_and_session):
""" Check that /302_overwrite overwrites the cookie, and that the client sends the new value. Passes in aiohttp 3.4.4, fails in 3.5.0 """host, session=host_and_session# Trigger Set-Cookie responseasyncwithsession.get(host+'/200') asresponse:
assertawaitresponse.text() ==''assertresponse.cookies.get('c').value=='something'asyncwithsession.get(host+'/302_overwrite') asresponse:
assertresponse.cookies.get('c').value=='something'assertawaitresponse.text() =='nothing'# <-- fails@pytest.mark.asyncioasyncdeftest_302_cookie(host_and_session):
""" Check that /302_clear clears the cookie, and that the client does not send the cookie either. Passes in aiohttp 3.5.2, fails in 3.5.3 """host, session=host_and_sessionasyncwithsession.get(host+'/200') asresponse:
assertawaitresponse.text() ==''assertresponse.cookies.get('c').value=='something'asyncwithsession.get(host+'/302_clear') asresponse:
assertresponse.cookies.get('c').value=='something'assertawaitresponse.text() ==''# <-- failsasyncdef_server_200(request: web.Request):
""" Returns the cookie value as a text body and sets the cookie to "something". """returnweb.Response(
body=request.cookies.get('c', ''),
headers={'Set-Cookie': 'c="something"; Path=/'})
asyncdef_server_302_overwrite(_request):
""" Sets the cookie to "nothing" and redirects to /200. """raiseweb.HTTPFound(
location='/200',
headers={'Set-Cookie': 'c="nothing"; Path=/'})
asyncdef_server_302_clear(_request):
""" Clears the cookie and redirects to /200. """clear='c=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/'raiseweb.HTTPFound(
location='/200',
headers={'Set-Cookie': clear})
defaccess_logger_class():
""" Helper to enable verbose logging for aiohttp >= 3.5.0. """try:
classAccessLogger(web.AbstractAccessLogger):
deflog(self, request, response, time):
defjoin(headers):
pairs= [f'{k}: {v}'fork, vinheaders.items()]
return'\n '.join([''] +pairs)
self.logger.info(f'Request: {request.method}{request.path}'f'{join(request.headers)}')
self.logger.info(f'Response: {response.status}'f'{join(response.headers)}')
return {'access_log_class': AccessLogger}
exceptAttributeError:
return {}
@pytest.fixture(name="host_and_session")asyncdefrun_server():
""" Fixture that spins up a sample server, and returns a hostname and a client session that can be used to connect to the server as a tuple. """log.access_logger.setLevel(logging.DEBUG)
log.access_logger.addHandler(logging.StreamHandler(sys.stdout))
withsocket.socket() assock:
sock.bind(('127.0.0.1', 0))
port=sock.getsockname()[1]
app=web.Application()
app.add_routes([
web.get('/302_clear', _server_302_clear),
web.get('/302_overwrite', _server_302_overwrite),
web.get('/200', _server_200)
])
runner=web.AppRunner(app, **access_logger_class())
awaitrunner.setup()
site=web.TCPSite(runner, port=port)
host='http://localhost:{}'.format(port)
awaitsite.start()
asyncwithClientSession() assession:
yieldhost, sessionawaitsite.stop()
awaitrunner.shutdown()
The text was updated successfully, but these errors were encountered:
Long story short
When a 302 sets or clears a cookie, newer versions of
aiohttp
do not correctly process this.Expected behaviour
Actual behaviour
In aiohttp 3.4.4:
In aiohttp 3.5.0:
In aiohttp 3.5.3:
Steps to reproduce
The text was updated successfully, but these errors were encountered: