I want to have a javascript client process get the HTTP status code that a server is returning when the client makes a websocket upgrade request and that request is unsuccessful.
I have my server returning HTTP 400 to indicate that a websocket upgrade is unsuccessful.
I am using Google Chrome and when i open the developer console I can see the following message:
WebSocket connection to 'wss://' failed: Error during WebSocket handshake: Unexpected response code: 400
However, the onerror handler does not contain this message, it receives a 1006 error but does not indicate that the closure occured as a result of getting HTTP 400.
How does a javascript developer handle handshake errors? I would like to provide the client with an informative message when they get a handshake error.
I have put the websocket error below, it does not seem to contain anything that I can use to indicate that this error is a result of a websocket handshake error.
Websocket Error: {"path":{"length":0},"cancelBubble":false,"returnValue":true,"srcElement":{"binaryType":"blob","protocol":"","extensions":"","bufferedAmount":0,"readyState":3,"url":"wss://<my address>","URL":"wss://<my address>"},"defaultPrevented":false,"timeStamp":1417828938039,"cancelable":false,"bubbles":false,"eventPhase":2,"currentTarget":{"binaryType":"blob","protocol":"","extensions":"","bufferedAmount":0,"readyState":3,"url":"wss://<my address>","URL":"wss://<my address>"},"target":{"binaryType":"blob","protocol":"","extensions":"","bufferedAmount":0,"readyState":3,"url":"wss://<my address>","URL":"wss://<my address>"},"type":"error"}
I am afraid there is no way from Javascript to know the HTTP status code of the negotiation.
There are defined closing codes, and 1006 only means that the connection is closed abruptly, but the protocol even allows to close the connection without providing a reason. That, together with the readyState API, are the only tools you have to diagnosed the reason of the problem.
Related
I'm trying to get a client to read the error message given when a connection to a WebSocket is failed.
The client attempts to connect to the socket with
this.socket = new WebSocket(url);
and the server handles this by listening for
server.on('upgrade', function upgrade(request, socket, head) {...})
If the client doesn't have the proper authentication, the server sends socket.write with a 401 error and a custom header containing a message saying why the connection failed, and then doing a socket.destroy(). After this, the client's this.socket is set to null as it isn't opened.
My question is, how can I get the client to read that custom error message so that I can display it to the user? If this isn't possible, what would be the best approach to communicate this error?
I tried to get a response from the server using axios, but then my web application froze instantly when the response was received by the client side
i got the error like this in my console
Failed to register/update a ServiceWorker for scope
‘http://localhost:3000/’: Load failed with status 404 for script
‘http://localhost:3000/sw.js’.
So, I have a rest api developed in Express. For authentication, I'm using cookies and to fetch user info I just do a get request to an endpoint that return me user info if its logged in or a 401 (Unauthorized) status code if its not. My concern is about, when I get a 401 status code, the chrome developer console print
Failed to load resource: the server responded with a status of 401
(Unauthorized)
It does not cause any bug in the client, just that It bothers me to see it hah.
Create an interceptor in the HTTP requests and upon received response, use the single line code console.clear(); to clear the console output.
In that way, even if you receive 401 or 403 or any response from server and a console error/warning is auto generated, then it will be auto cleared as well!
My socket currently throws net::ERR_CONNECTION_REFUSED because the server isn't running, which I want it to do at the moment.
The problem is that the following piece of code doesn't catch the error. In the console I see an exception on line 2 (with net::ERR_CONNECTION_REFUSED) which I believe shouldn't happen as it's within a try statement.
1 try {
2 ws = new WebSocket('ws://'+ host + ':' + port + '/');
3 }
4 catch (err) {
5 console.log('This never prints');
6 }
7 ws.onerror = function (error) {
8 console.log(error);
9 };
So my question is why is it not being caught?
What I ultimately want is the error message to be displayed elsewhere, but I can't catch it, and line 8 prints an "event" object which doesn't mention net::ERR_CONNECTION_REFUSED, so I'm not sure how to get the error message out.
The WebSocket's connection-time error causes a dispatched event, not a thrown value. This is because throw operations must be synchronous. In order to handle all connection-time errors as thrown errors, the WebSocket constructor would need to completely suspend all script execution and UI interaction until the entire WebSocket handshake had completed. Instead, the connection process runs asynchronously, thereby allowing the browser thread to continue working while the WebSocket connection initializes in the background. Because of the connection's asynchronous nature, the WebSocket must report errors via error events, since the synchronous new WebSocket operation has already finished by the time the asynchronous connection task encounters an error.
The ERR_CONNECTION_REFUSED message you see is purely for the benefit of developers; it is not accessible to the script in any way. It does not have any representation within the JavaScript environment. It's just a red-colored message that appears in your console to inform you, the human looking at the browser, about an error.
The error handler event is the correct place to respond to failure, but the lack of script-readable connection-time error information is by design. From the WHATWG spec for the WebSocket API:
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.
[...] Allowing a script to distinguish these cases would allow a script to probe the user's local network in preparation for an attack.
The browser is deliberately omitting any useful information as required by the spec. The spec authors are concerned that access to this information could allow a malicious Web page to gain information about your network, so they require browsers report all connection-time errors in an indistinguishable way.
I tried creating fiddle with it
and I am able to see line printed.
host='localhost';
port=100;
try {
ws = new WebSocket('ws://'+ host + ':' + port + '/');
}
catch (err) {
console.log('This never prints');
}
ws.onerror = function (error) {
console.log(error);
};
https://jsfiddle.net/xzumgag0/
Chrome based browsers: In my case I just wanted to get rid of the error message from the console. In which case you can enter this regex into the console filter:
-/Websocket\sconnection.*failed/
have node.js websockets running through haproxy, and has been running successfully for several months.
now now giving error
Error during WebSocket handshake: 'Connection' header value is not 'Upgrade'
same code / setup is still working on development computer
any ideas / suggestions more than appreciated!
firefox works ok! chrome errors from main server, but works correctly local
There is something terribly concerning here with this error message. The "Connection" header value should not be "Upgrade" but should contain "Upgrade". "Connection" is an HTTP header field which is hop-by-hop and may contain multiple tokens, including Upgrade, but also a number of other ones. This is in RFC6455 page 17 :
" 5. The request MUST contain an |Upgrade| header field whose value MUST include the "websocket" keyword."
So I think that something is wrong in the server software, or at least in the error message. You should definitely take a network capture to be sure.