Skip to content

[4.2] Add websocket callbacks#3742

Draft
T4rk1n wants to merge 6 commits intov4.2from
websocket-callbacks
Draft

[4.2] Add websocket callbacks#3742
T4rk1n wants to merge 6 commits intov4.2from
websocket-callbacks

Conversation

@T4rk1n
Copy link
Copy Markdown
Contributor

@T4rk1n T4rk1n commented Apr 14, 2026

Implements WebSocket-based callbacks for Dash, enabling real-time bidirectional communication between the renderer and backend. This replaces HTTP POST requests with persistent WebSocket connections for reduced latency and server-push capabilities.

Architecture

  ┌─────────────────────────────────────────────────────────────────────────┐                                                                                                                                               
  │ Browser Tab 1                          Browser Tab 2                    │                                                                                                                                              
  │ ┌─────────────┐                       ┌─────────────┐                   │                                                                                                                                               
  │ │  Renderer   │                       │  Renderer   │                   │                                                                                                                                               
  │ └──────┬──────┘                       └──────┬──────┘                   │                                                                                                                                               
  │        │ postMessage                         │ postMessage              │                                                                                                                                               
  │        └────────────┬───────────────────────┘                           │                                                                                                                                               
  │                     ▼                                                   │                                                                                                                                              
  │         ┌─────────────────────┐                                         │                                                                                                                                               
  │         │  SharedWorker       │  (one per origin)                       │                                                                                                                                               
  │         │  dash-ws-worker     │                                         │                                                                                                                                               
  │         └──────────┬──────────┘                                         │                                                                                                                                               
  └────────────────────│────────────────────────────────────────────────────┘                                                                                                                                               
                       │ WebSocket                                                                                                                                                                                          
                       ▼                                                                                                                                                                                                    
  ┌─────────────────────────────────────────────────────────────────────────┐                                                                                                                                               
  │ Server (FastAPI)                                                        │                                                                                                                                              
  │   WebSocket Endpoint: /_dash-ws-callback                                │                                                                                                                                              
  └─────────────────────────────────────────────────────────────────────────┘                                                                                                                                               

A SharedWorker maintains a single WebSocket connection shared across all browser tabs, routing messages between renderers and the server.

Usage

Use with fastapi pip install dash[fastapi]==4.2.0rc1 (when available).

# Enable WebSocket callbacks                                                                                                                                                                                              
  app = Dash(__name__, backend="fastapi", websocket_callbacks=True)                                                                                                                                                                            
                                                                                                                                                                                                                            
  @callback(Output("output", "children"), Input("input", "value"))                                                                                                                                                          
  async def update(value):                                                                                                                                                                                                        
      # Stream intermediate updates via WebSocket                                                                                                                                                                           
      ws = ctx.get_websocket                                                                                                                                                                                                
      if ws:                                                                                                                                                                                                                
          await ws.set_prop("progress", "value", 50)                                                                                                                                                                        
                                                                                                                                                                                                                            
      return f"Result: {value}"

Example app in wsapp.py (to be deleted before full release alongside quart_app.py)

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 14, 2026

Thank you for your contribution to Dash! 🎉

This PR is exempt from requiring a linked issue due to its labels.

@BSd3v
Copy link
Copy Markdown
Contributor

BSd3v commented Apr 14, 2026

First, I want to say that this is a great step at the flexibility of Dash and reducing network load.


I have some concerns with security of the app level websockets that are currently implemented:

  1. Initial Handshake Origin Validation
  • Concern: The current implementation lacks strict validation of the Origin header during the WebSocket handshake.
  • Risk: Without explicit origin validation, the app is exposed to Cross-Site WebSocket Hijacking and unauthorized domains opening connections, leading to data leakage or session compromise.
  • Recommendation: Implement an explicit check to only allow upgrades (wss://) from trusted domains. Reject any connection attempts with a mismatched or missing Origin header.
  1. Developer Control Over WebSocket and Disconnect
  • Concern: The framework offers limited or no hooks for developers to explicitly close or disconnect specific WebSocket connections (e.g., on suspicious activity, user ban, or policy violation).
  • Risk: Persistent, unattended connections could be abused, or connections that should be invalidated (e.g., on role change, session revoke) might remain open, with the app developer having no way to enforce disconnect logic.
  • Recommendation: Add mechanisms for app-level code to enumerate active connections and forcibly close or invalidate sessions as needed (e.g., via a server API or callback).
  1. Supporting Login/Logout and Session Lifecycle
  • Concern: There is insufficient handling in the PR for session lifecycle events such as login, logout, or user switching.
  • Risk: WebSocket connections might remain active after a user logs out or switches accounts. This can result in privilege escalation, session fixation, or data leaks across users or sessions.
  • Recommendation: Tie the lifetime of a WebSocket connection to the authenticated user’s session. Enforce immediate disconnection on logout/session expiration, and require establishing a new, authenticated WebSocket on subsequent login.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants