-
Notifications
You must be signed in to change notification settings - Fork 87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
aiohttp 4.0.0a1 compatibility issue #396
Comments
Thanks for the report. |
Thank you! |
I'm wondering do you need context vars support or something also? Context vars support can be backported to 3.x line and released as a part of aiohttp 3.7. If it solves your needs I'll happy to backport. Seems like not only you need the feature. |
Hi @asvetlov, Yes, we do need context vars support, that's why we're using the 4.0 alpha. Anyway, I created my own session middleware, compatible with aiohttp 4.0 for now. This seems to work fine. In case anyone is interested, this is what we have: import uuid
from contextvars import ContextVar
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict
from aiohttp.web import Request, StreamResponse
from aiohttp.web_exceptions import HTTPMove
from our_database_backend import Database, SessionNotFoundError # custom.
__all__ = ["SessionMiddleware", "session"]
# The session context variable that's populated by the `SessionMiddleware`.
session: ContextVar[Dict[str, Any]] = ContextVar("session", default={})
if TYPE_CHECKING:
# Middleware type, see:
# https://github.com/aio-libs/aiohttp/blob/master/aiohttp/web_app.py
_Handler = Callable[[Request], Awaitable[StreamResponse]]
class SessionMiddleware:
def __init__(self, database: Database, cookie_name="candela_session") -> None:
self.database = database
self.cookie_name = cookie_name
async def __call__(self, request: Request, handler: "_Handler") -> StreamResponse:
session_key = request.cookies.get(self.cookie_name)
# Load session from database, if we have a session key.
if session_key is None:
new_session = True
else:
try:
session_data = await self.database.load_session(session_key)
except SessionNotFoundError:
new_session = True
else:
new_session = False
if new_session:
session_key = str(uuid.uuid4())
session_data = {}
session.set(session_data)
cookie_header = f"{self.cookie_name}={session_key}"
try:
response = await handler(request)
# Add session cookie to response.
# response.set_cookie(self._cookie_name, session_key)
if new_session:
response.headers["Set-Cookie"] = cookie_header
return response
except HTTPMove as move:
# Add header to redirect response.
move.headers["Set-Cookie"] = cookie_header
raise
finally:
# Store new session in DB.
await self.database.store_session(session_key, session.get())
|
So, one thing I missed in aiohttp 4.0, was a Thanks again for aiohttp, it's absolutely great. |
My pleasure!
|
aio-libs/aiohttp#4271 provides backport of contextvar related changes back to 3.x line. |
As seen in #506 this is also broken with aiohttp 3.7.2 |
I think the isinstance() changes in #512 and the more recent addition of cookies on HTTPExceptions should fix this issue. |
FYI: By using |
Right, though that behaviour is deprecated, so you should remember to switch it back once 3.8 is released. |
I think this issue is fixed now (pending releases). |
Hi there, first of all thanks for creating this library!
The newest aiohttp alpha has a change that expects redirects to be raised as exceptions.
This is not supported by the session middleware, because
HTTPFound
is not an instance ofStreamResponse
. It seems also more complex then adding a simpleisinstance()
check in__init__.py
, because after doing this, the session is not created correctly at a302 Found
page. This is common when using oauth authentication though.(The reason for using the latest aiohttp alpha is because I need the context variable support.)
Thanks!
The text was updated successfully, but these errors were encountered: