I have a django asgi app that is served by daphne. I am trying to add Server Sent events to stream data from server to client.
My asgi.py:
"""
ASGI config for app project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
application = get_asgi_application()
My django view is below:
import uuid
from django.http import StreamingHttpResponse
from rest_framework.views import APIView
from .sse_helper import register_connection
import logging
log = logging.getLogger("sse_handler")
class MySseView(APIView):
# authentication_classes = [SessionAuthentication]
# permission_classes = [IsAuthenticated]
def get(self, request):
log.info("Recived get request")
response = StreamingHttpResponse(content_type="text/event-stream")
# Set headers to enable SSE support
response["Cache-Control"] = "no-cache"
response["Connection"] = "keep-alive"
# Generate a unique ID for this connection
connection_id = str(uuid.uuid4())
business_id = "foo"
# Register the connection in the dictionary
register_connection(connection_id, str(business_id), response)
return response
The registered connections are processed by a background thread like this:
sse_connections = {}
def register_connection(connection_id, business_id, response):
log.info("Registering sse connection %s for business %s" % (connection_id, business_id))
sse_connections[connection_id + '#' + business_id] = response
def handle_events():
while True:
# Iterate over the dictionary of connections
log.info("Running handle_events on %d items" % len(sse_connections))
for connection_id, response in sse_connections.items():
# Send an SSE event to the client
event = 'message'
data = f'Hello from background thread! ({time.time()})'
message = f'event: {event}\ndata: {data}\n\n'
response.write(message)
log.info("wrote message")
# Sleep for a while before sending the next event
time.sleep(1)
def start():
log.info("Starting bg thread for sse")
# Start a background thread to send SSE events
thread = threading.Thread(target=handle_events)
thread.daemon = True
thread.start()
I am running this using daphne server. However i see that daphne is closing the connection after sending response. Is it because of my view being sync?
Below is daphne response:
INFO 2023-03-21 04:26:35,077 views 9642 140491307861568 Recived get request
INFO 2023-03-21 04:26:35,077 sse_helper 9642 140491307861568 Registering sse connection df664db3-12cb-499f-a930-e0b51175058b for business foo
DEBUG 2023-03-21 04:26:35,083 http_protocol 9642 140491467215296 HTTP 200 response started for ['127.0.0.1', 48020]
DEBUG 2023-03-21 04:26:35,083 http_protocol 9642 140491467215296 HTTP close for ['127.0.0.1', 48020]
INFO 2023-03-21 04:26:35,084 _observer 9642 140491467215296 "127.0.0.1" - - [21/Mar/2023:04:26:34 +0000] "GET /events/ HTTP/1.1" 200 - "https://localhost:8001/events" "PostmanRuntime/7.31.1"
DEBUG 2023-03-21 04:26:35,084 http_protocol 9642 140491467215296 HTTP response complete for ['127.0.0.1', 48020]
127.0.0.1:48020 - - [21/Mar/2023:04:26:35] "GET /events/" 200 -