Pregunta

I'm having trouble opening a websocket in Chrome. It seems that there is some CORS policy in chrome for websockets.

If I am on www.example.com and attempt to open the websocket at api.example.com it'll say pending on the console network tab, and will fire the onerror with a message WebSocket connection to 'wss://api.example.com' failed: Connection closed before receiving a handshake response. If I look at the server I do not see a request for a web socket connection being made, so there is no options request to respond to, or Ability to set an Access-Control-Allow-Origin header. However if I first make a request to api.example.com which on the browser will redirect me back to www.example.com it'll work fine.

Are you required to use the same origin for websocket requests in chrome?

Note: this issue is only with chrome.

¿Fue útil?

Solución 2

I came across this issue again. I still haven't figured out why, but making an OPTIONS (or any other) request to the subdomain first allows the connection to be opened.

This only seems to be a problem with wss connections, and has popped up across multiple domains and certificates.

Otros consejos

There is no browser enforced CORS with WebSocket. Here are 2 things that can go wrong (assuming you use both HTTPS and WSS):

  • the server enforces an Origin. The Origin HTTP header is set by the browser to the origin of the HTML page containing the JavaScript that is opening the WebSocket connection. A server MAY check that header and deny. But since you say other browsers are working (which?), this is unlikely
  • since you are using wss, the server certificate MUST be completely valid, and acceptable to the browser without any user interaction. Is this the case?

This sounds like it has to do with making cross-origin requests that are not "simple". HTTP requests that are not simple are "preflighted" by the browser (Chrome at least) with "OPTIONS" automatically. I'm guessing the browser is just enforcing this behavior.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

For me, this ended up being because Socket.IO uses HTTP to set up the connection. Their docs mention how to resolve this. For me, changing my server initialization as mentioned in the docs fixed it:

const io = new socketIo.Server(5555, {
    cors: {
        origin: "http://localhost:4200"  // Angular port
    }
});

If you are not the one running the server or don't know the stack used, it will be hard to figure out.

One example of server software with websocket is gotty (it uses implementation github.com/gorilla/websocket).

For gotty server to allow any origin value, command & params to start it must be:

 > gotty -w  --ws-origin ".*" bash

--ws-origin value A regular expression that matches origin URLs to be accepted by WebSocket. No cross origin requests are acceptable by default [$GOTTY_WS_ORIGIN]

On a chrome console, you can now execute below without errors:

url = 'ws://<host>:<port>/ws';  
const w = new WebSocket(url) 

It seems the protocol do mention it:

The |Origin| header field [RFC6454] is used to protect against
unauthorized cross-origin use of a WebSocket server by scripts using
the WebSocket API in a web browser.

Try setting an Access-Control-Allow-Origin header on api.example.com that allows www.example.com.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top