A lightweight, real-time chat application built with Python using the aiohttp framework. This application provides user registration, authentication, and real-time messaging capabilities through WebSockets.
- User registration and authentication
- Session management with automatic expiration
- Real-time messaging via WebSockets
- Online user tracking
- Event notifications for user join/leave events
The application is built using:
- aiohttp: Asynchronous HTTP client/server framework
- SQLite: Lightweight database for user information storage
- WebSockets: For real-time bidirectional communication
Register a new user.
Request Body:
{
"username": "johndoe"
}Responses:
201 Created: User successfully registered with a key400 Bad Request: Invalid username format (must be alphanumeric and max 32 characters)409 Conflict: Username already exists422 Unprocessable Entity: Invalid request format
Authenticate with a user key.
Request Body:
{
"key": "user_key_here"
}Responses:
200 OK: Successfully authenticated, sets a session cookie401 Unauthorized: Invalid key422 Unprocessable Entity: Invalid request format
End the current user session.
Responses:
200 OK: Session terminated successfully
Retrieve a list of currently online users.
Responses:
200 OK: Returns list of online users401 Unauthorized: Session invalid or expired422 Unprocessable Entity: Missing session cookie
Get information about a specific user. Use @me to get information about the current user.
Responses:
200 OK: Returns user information401 Unauthorized: Session invalid or expired422 Unprocessable Entity: Missing session cookie501 Not Implemented: User lookup not implemented (except for@me)
Connect to the WebSocket server for real-time messaging.
Events:
join: Sent when a user connects to the chatleave: Sent when a user disconnects from the chatmessage: Chat message from a user
Message Format (Send):
{
"message": "Hello, world!"
}Message Format (Receive):
{
"message": "Hello, world!",
"author": "johndoe"
}Acknowledgment Format: When a message is sent by a client, the server sends an acknowledgment back to the sender:
Success Acknowledgment:
{
"status": true
}Error Acknowledgment:
{
"status": false,
"code": "message_too_long"
}Possible error codes:
message_too_long: Message exceeds the 300 character limit
Event Format:
{
"event": "join|leave",
"username": "johndoe"
}Responses:
101 Switching Protocols: WebSocket connection established401 Unauthorized: Session invalid or expired409 Conflict: User already has an active WebSocket connection422 Unprocessable Entity: Missing session cookie
- Sessions expire after 1 hour of inactivity
- Each user can have only one active WebSocket connection at a time
- Sessions are automatically cleaned up by a background task
The application uses SQLite to store user information:
username: Unique user identifier (alphanumeric, max 32 characters)key: Authentication key for the user
-
Ensure you have the required dependencies installed:
pip3 install -r requirements.txt -
Start the server:
python3 main.py -
The server will start on
0.0.0.0:7777
For production deployment, the application should be run with SSL/TLS certificates to ensure secure communication:
-
Using with Nginx as a Reverse Proxy (Recommended):
The production service at
chat.piraterna.orgis proxied using Nginx which handles the SSL/TLS termination. This setup allows:- Proper SSL/TLS certificate management
- WebSocket protocol upgrade handling
- Additional security headers
- Load balancing if needed
Example Nginx configuration for WebSocket proxying:
server { listen 443 ssl; server_name chat.piraterna.org; ssl_certificate /path/to/certificate.crt; ssl_certificate_key /path/to/private.key; location / { proxy_pass http://localhost:7777; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
-
Direct SSL Configuration:
Alternatively, the application can be run with SSL directly:
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_context.load_cert_chain('certificate.crt', 'private.key') web.run_app(app, host="0.0.0.0", port=7777, ssl_context=ssl_context)
This requires modifying the
main.pyfile to include SSL context configuration.
- Username validation ensures only alphanumeric characters are accepted
- Session keys are cryptographically secure 32-character strings
- Inactive sessions are automatically expired and cleaned up
- WebSocket connections are properly closed during server shutdown
- SSL/TLS encryption is essential in production to secure data transmission
- CORS headers should be configured appropriately in production