CORS for Real-Time Apps: Socket.IO and SignalR

Real-time apps make CORS weirder than plain old fetch(). A normal API request is easy to reason about: browser sends an Origin, server returns Access-Control-Allow-Origin, done. Real-time stacks like Socket.IO and SignalR add negotiation endpoints, long polling fallbacks, credentials, sticky sessions, and WebSocket upgrades. That combination creates the kind of bug where everything works locally, then production starts throwing “CORS policy blocked” while your websocket dashboard looks perfectly healthy. I’ve hit this enough times that I now treat real-time CORS as a separate problem, not just “API CORS but more.” ...

June 19, 2026 · 7 min · headertest.com

How CORS Works with WebSocket Connections

If you’ve worked with fetch() long enough, CORS feels familiar: preflights, Access-Control-Allow-Origin, blocked responses, weird credentials rules. Then you open a WebSocket from a browser and things get weird fast. You expect CORS to kick in. Usually it doesn’t. That surprises a lot of people because WebSockets start as an HTTP request. But the browser does not apply the normal CORS enforcement model to a WebSocket upgrade the same way it does for fetch() or XHR. Instead, browsers send an Origin header during the handshake, and the server is expected to decide whether to accept the connection. ...

April 3, 2026 · 7 min · headertest.com