piratchat/README.md
2025-04-03 07:35:54 +02:00

5.7 KiB

Piratchat

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.

Features

  • User registration and authentication
  • Session management with automatic expiration
  • Real-time messaging via WebSockets
  • Online user tracking
  • Event notifications for user join/leave events

Architecture

The application is built using:

  • aiohttp: Asynchronous HTTP client/server framework
  • SQLite: Lightweight database for user information storage
  • WebSockets: For real-time bidirectional communication

API Endpoints

Authentication

POST /api/register

Register a new user.

Request Body:

{
  "username": "johndoe"
}

Responses:

  • 201 Created: User successfully registered with a key
  • 400 Bad Request: Invalid username format (must be alphanumeric and max 32 characters)
  • 409 Conflict: Username already exists
  • 422 Unprocessable Entity: Invalid request format

POST /api/login

Authenticate with a user key.

Request Body:

{
  "key": "user_key_here"
}

Responses:

  • 200 OK: Successfully authenticated, sets a session cookie
  • 401 Unauthorized: Invalid key
  • 422 Unprocessable Entity: Invalid request format

GET /api/logout

End the current user session.

Responses:

  • 200 OK: Session terminated successfully

User Information

GET /api/online

Retrieve a list of currently online users.

Responses:

  • 200 OK: Returns list of online users
  • 401 Unauthorized: Session invalid or expired
  • 422 Unprocessable Entity: Missing session cookie

GET /api/user/{username}

Get information about a specific user. Use @me to get information about the current user.

Responses:

  • 200 OK: Returns user information
  • 401 Unauthorized: Session invalid or expired
  • 422 Unprocessable Entity: Missing session cookie
  • 501 Not Implemented: User lookup not implemented (except for @me)

WebSocket Communication

GET /ws

Connect to the WebSocket server for real-time messaging.

Events:

  • join: Sent when a user connects to the chat
  • leave: Sent when a user disconnects from the chat
  • message: 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 established
  • 401 Unauthorized: Session invalid or expired
  • 409 Conflict: User already has an active WebSocket connection
  • 422 Unprocessable Entity: Missing session cookie

Session Management

  • 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

Database Structure

The application uses SQLite to store user information:

  • username: Unique user identifier (alphanumeric, max 32 characters)
  • key: Authentication key for the user

Running the Application

  1. Ensure you have the required dependencies installed:

    pip3 install -r requirements.txt 
    
  2. Start the server:

    python3 main.py
    
  3. The server will start on 0.0.0.0:7777

Production Deployment

For production deployment, the application should be run with SSL/TLS certificates to ensure secure communication:

  1. Using with Nginx as a Reverse Proxy (Recommended):

    The production service at chat.piraterna.org is 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;
        }
    }
    
  2. 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.py file to include SSL context configuration.

Security Considerations

  • 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