24

I created a WebSocket client in JavaScript

if ("WebSocket" in window) {            
    ws = new WebSocket(url);
    ws.binaryType = "arraybuffer";      
} else if ("MozWebSocket" in window) {  
    ws = new MozWebSocket(url);
    ws.binaryType = "arraybuffer";  
}

and a WebSocket server application. For certain cases I programmed the server to reject the connection request and provide an error code.

In e.g. Firefox Console then a message is shown

Firefox can't establish a connection to the server at ws://123.123.123.123:1234/.

and it provides the status code

HTTP/1.1 403 

which is the error code that I have sent by my WebSocket server.

My question is: how can I read this status code in my JavaScript client?

ws.onerror = function(e) {
    console.log(e);     
};   
ws.onclose = function(e) {
    console.log(e); 
};

are both called, but none of the Event objects contains this error code.

Artas
  • 315
  • 1
  • 2
  • 8
  • 1
    you want http error codes from a non http protocol? – dandavis Feb 13 '14 at 18:37
  • I found this way of passing an error code from server to client before establishing the WebSocket connection and would like to have the error code in my JavaScript program and not only in the Firefox console. Don't know, if this is possible. I am new to WebSocket and JavaScript, so please also tell me, if this is a stupid idea. – Artas Feb 13 '14 at 18:53
  • i think you can only rely on the standard cookie-cutter error codes as listed in https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent – dandavis Feb 13 '14 at 18:56
  • I tried two of the standard error codes (1003: CLOSE_UNSUPPORTED, 4001: Available for use by applications) and it is exactly the same. I think it doesn't matter which error code I am using. – Artas Feb 14 '14 at 09:14
  • 1
    When the upgrade request failed it is still HTTP protocol, not WebSocket protocol. – bartholomaios Feb 16 '22 at 08:13

1 Answers1

37

The spec forbids reading the HTTP status code (or anything like it) from the WebSocket object because otherwise the WebSocket object could be used to probe non-WebSocket endpoints, which would be a security issue:

User agents must not convey any failure information to scripts in a way that would allow a script to distinguish the following situations:

  • A server whose host name could not be resolved.
  • A server to which packets could not successfully be routed.
  • A server that refused the connection on the specified port.
  • A server that failed to correctly perform a TLS handshake (e.g., the server certificate can't be verified).
  • A server that did not complete the opening handshake (e.g. because it was not a WebSocket server).
  • A WebSocket server that sent a correct opening handshake, but that specified options that caused the client to drop the connection (e.g. the server specified a subprotocol that the client did not offer).
  • A WebSocket server that abruptly closed the connection after successfully completing the opening handshake.

https://www.w3.org/TR/websockets/#feedback-from-the-protocol


There is another way to do it though!

The WebSocket protocol allows for custom close codes:

4000-4999

Status codes in the range 4000-4999 are reserved for private use and thus can't be registered. Such codes can be used by prior agreements between WebSocket applications. The interpretation of these codes is undefined by this protocol.

https://www.rfc-editor.org/rfc/rfc6455#section-7.4.2

In your server-side logic, even when you ultimately want to reject the connection (like say the user is currently unauthenticated), do this instead:

  1. Accept the WebSocket connection
  2. Immediately close the connection with a custom close status

The client can now look at the CloseEvent.code to know why the connection was rejected.

You don't need to do this every time the server wants to reject a WebSocket connection. For example, I'd still reject the connection with a 4xx HTTP status if the request isn't a proper WebSocket request, or for security reasons (like if the anti-CSWSH Origin check fails). You only need to use the WebSocket close status for cases that you want the client-side logic to handle.

Community
  • 1
  • 1
Michael Kropat
  • 14,557
  • 12
  • 70
  • 91
  • 1
    What about the section (https://www.rfc-editor.org/rfc/rfc6455#section-4.1) of RFC which says: If the status code received from the server is not 101, the client handles the response per HTTP [RFC2616] procedures. In particular, the client might perform authentication if it receives a 401 status code; the server might redirect the client using a 3xx status code (but clients are not required to follow them), etc. Otherwise, proceed as follows. – bartholomaios Feb 16 '22 at 08:10