Basic Example ============= This example demonstrates a simple WebSocket application using Chanx. It includes an echo service with authentication and structured messages, showing the fundamental features of the framework. Project Setup ------------- First, let's create a basic Django project structure: .. code-block:: bash myproject/ ├── manage.py ├── myproject/ │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── echo/ ├── __init__.py ├── consumers.py ├── messages.py ├── routing.py └── templates/ └── echo/ └── index.html Message Types ------------- Define message types in `echo/messages.py`: .. code-block:: python from typing import Any, Literal, Optional from chanx.messages.base import BaseMessage from chanx.messages.incoming import PingMessage class EchoMessage(BaseMessage): """Message for echoing text back to the client.""" action: Literal["echo"] = "echo" payload: str class StatusMessage(BaseMessage): """Message for sending status updates.""" action: Literal["status"] = "status" payload: str # Define incoming message union EchoIncomingMessage = PingMessage | EchoMessage WebSocket Consumer ------------------ Create a consumer in `echo/consumers.py`: .. code-block:: python from typing import Any from rest_framework.authentication import SessionAuthentication from rest_framework.permissions import IsAuthenticated from chanx.generic.websocket import AsyncJsonWebsocketConsumer from chanx.messages.incoming import PingMessage from chanx.messages.outgoing import PongMessage from echo.messages import EchoIncomingMessage, EchoMessage, StatusMessage class EchoConsumer(AsyncJsonWebsocketConsumer[EchoIncomingMessage]): """ Simple echo consumer that responds to messages. Demonstrates basic authentication and message handling with Chanx. """ # Authentication setup authentication_classes = [SessionAuthentication] permission_classes = [IsAuthenticated] # Enable completion messages send_completion = True async def post_authentication(self) -> None: """Actions after successful authentication.""" # Send a welcome message after connection authentication user = self.user await self.send_message( StatusMessage(payload=f"Welcome, {user.username}!") ) async def receive_message(self, message: EchoIncomingMessage, **kwargs: Any) -> None: """Handle incoming messages.""" # Handle different message types using pattern matching match message: case PingMessage(): # Respond to ping with pong await self.send_message(PongMessage()) case EchoMessage(payload=payload): # Echo the message back with the user's name user = self.user echo_text = f"{user.username}: {payload}" await self.send_message(EchoMessage(payload=echo_text)) case _: # Handle any other messages pass WebSocket Routing ----------------- Set up routing in `echo/routing.py`: .. code-block:: python from channels.routing import URLRouter from chanx.routing import path from echo.consumers import EchoConsumer # Important: name this variable 'router' for string-based includes router = URLRouter([ path('echo/', EchoConsumer.as_asgi()), ]) ASGI Configuration ------------------ Configure the ASGI application in `myproject/asgi.py`: .. code-block:: python import os from channels.routing import ProtocolTypeRouter from channels.security.websocket import OriginValidator from channels.sessions import CookieMiddleware from django.core.asgi import get_asgi_application from django.conf import settings from chanx.routing import include os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings") django_asgi_app = get_asgi_application() routing = { "http": django_asgi_app, "websocket": OriginValidator( CookieMiddleware(include("echo.routing")), settings.CORS_ALLOWED_ORIGINS + settings.CSRF_TRUSTED_ORIGINS, ), } application = ProtocolTypeRouter(routing) Settings Configuration ---------------------- Update `myproject/settings.py` with Channels and Chanx settings: .. code-block:: python INSTALLED_APPS = [ # Django apps "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", # Third-party apps "daphne", "channels", "rest_framework", "chanx.playground", # Enable the WebSocket playground # Local apps "echo", ] # Channels configuration ASGI_APPLICATION = "myproject.asgi.application" CHANNEL_LAYERS = { "default": { "BACKEND": "channels.layers.InMemoryChannelLayer" # For production, use Redis: # "BACKEND": "channels_redis.core.RedisChannelLayer", # "CONFIG": { # "hosts": [("127.0.0.1", 6379)], # }, } } # Chanx settings CHANX = { "SEND_COMPLETION": True, "SEND_AUTHENTICATION_MESSAGE": True, "LOG_RECEIVED_MESSAGE": True, "LOG_SENT_MESSAGE": True, } # CORS/CSRF settings for WebSocket CORS_ALLOWED_ORIGINS = ["http://localhost:8000"] CSRF_TRUSTED_ORIGINS = ["http://localhost:8000"] HTML Template ------------- Create a simple frontend in `echo/templates/echo/index.html`: .. code-block:: html