Skip to content

Commit

Permalink
Use the async sessions api if it exists
Browse files Browse the repository at this point in the history
  • Loading branch information
bigfootjon committed Apr 21, 2024
1 parent 8087d47 commit 0bcd7a4
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 7 deletions.
14 changes: 8 additions & 6 deletions channels/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import time
from importlib import import_module

import django
from django.conf import settings
from django.contrib.sessions.backends.base import UpdateError
from django.core.exceptions import SuspiciousOperation
Expand Down Expand Up @@ -163,9 +164,7 @@ def __init__(self, scope, send):

async def resolve_session(self):
session_key = self.scope["cookies"].get(self.cookie_name)
self.scope["session"]._wrapped = await database_sync_to_async(
self.session_store
)(session_key)
self.scope["session"]._wrapped = self.session_store(session_key)

async def send(self, message):
"""
Expand All @@ -183,7 +182,7 @@ async def send(self, message):
and message.get("status", 200) != 500
and (modified or settings.SESSION_SAVE_EVERY_REQUEST)
):
await database_sync_to_async(self.save_session)()
await self.save_session()
# If this is a message type that can transport cookies back to the
# client, then do so.
if message["type"] in self.cookie_response_message_types:
Expand Down Expand Up @@ -221,12 +220,15 @@ async def send(self, message):
# Pass up the send
return await self.real_send(message)

def save_session(self):
async def save_session(self):
"""
Saves the current session.
"""
try:
self.scope["session"].save()
if django.VERSION >= (5, 1):
await self.scope["session"].asave()
else:
await database_sync_to_async(self.scope["session"].save)()
except UpdateError:
raise SuspiciousOperation(
"The request's session was deleted before the "
Expand Down
52 changes: 51 additions & 1 deletion tests/test_http.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import re
from importlib import import_module
from django.conf import settings

import pytest

import django
from channels.consumer import AsyncConsumer
from channels.db import database_sync_to_async
from channels.sessions import CookieMiddleware, SessionMiddlewareStack
Expand Down Expand Up @@ -93,7 +96,7 @@ async def test_session_samesite_invalid(samesite_invalid):

@pytest.mark.django_db(transaction=True)
@pytest.mark.asyncio
async def test_muliple_sessions():
async def test_multiple_sessions():
"""
Create two application instances and test then out of order to verify that
separate scopes are used.
Expand Down Expand Up @@ -123,3 +126,50 @@ async def http_request(self, event):

first_response = await first_communicator.get_response()
assert first_response["body"] == b"/first/"


@pytest.mark.django_db(transaction=True)
@pytest.mark.asyncio
async def test_session_saves():
"""
Saves information to a session and validates that it actually saves to the backend
"""

async def inner(scope, receive, send):
send(scope["path"])

class SimpleHttpApp(AsyncConsumer):
@database_sync_to_async
def set_fav_color(self):
self.scope["session"]["fav_color"] = "blue"

async def http_request(self, event):
if django.VERSION >= (5, 1):
await self.scope["session"].aset("fav_color", "blue")
else:
await self.set_fav_color()
await self.send(
{"type": "http.response.start", "status": 200, "headers": []}
)
await self.send(
{
"type": "http.response.body",
"body": self.scope["session"].session_key.encode(),
}
)

app = SessionMiddlewareStack(SimpleHttpApp.as_asgi())

communicator = HttpCommunicator(app, "GET", "/first/")

response = await communicator.get_response()
session_key = response["body"].decode()

SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
session = SessionStore(session_key=session_key)
if django.VERSION >= (5, 1):
session_fav_color = await session.aget("fav_color")
else:
session_fav_color = await database_sync_to_async(session.get)("fav_color")

assert session_fav_color == "blue"

0 comments on commit 0bcd7a4

Please sign in to comment.