-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Revisiting Invalid WebSocket frame: RSV1 must be clear #2109
Comments
Alright, I tried this on Linux and it worked just fine. So it seems the problem is with MacOS, incredibly. I come to this conclusion because 1) all Mac browsers are affected (Chromium, Safari, and Firefox), and 2) I found a little bit of discussion of this in Apple forums. My computer is pretty up to date, but I see that it is a little bit behind now. I'm going to try updating and see if that resolves the issue. |
I can't reproduce.
const { WebSocketServer } = require('ws');
const http = require('http');
const data = `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
(function () {
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
ws.send('hello');
};
})();
</script>
</body>
</html>`;
const server = http.createServer();
const wss = new WebSocketServer({ server });
server.on('request', function (req, res) {
res.setHeader('Content-Type', 'text/html');
res.end(data);
});
wss.on('connection', function (ws) {
ws.on('message', function (buf) {
console.log(buf.toString());
});
ws.send('hello');
});
server.listen(8080, function () {
console.log('Open http://127.0.0.1:8080 in the brower');
}); Tested on Chrome 108.0.5359.124 and Safari 16.2 (18614.3.7.1.5). |
Very strange, I can still reproduce with your code, after updating to MacOS 13.1 and checking with npx envinfo, and with the exact same Chrome build. So we have the same OS and browser. My node is a bit out of date, so let me update that and see if that somehow helps. If not, I'm not sure what the issue could possibly be. |
Tried with Node v18.12.1, with the same problem still. So our OS, browser, node, and ws versions are all identical, and yet we have different behavior. |
Okay, new discovery. I ran my original code in a remote server, hit it using Chrome, and it all worked properly. So it appears that the problem only happens when I am using localhost. Don't know why my localhost is bad yet. |
I guess it is some software installed on you Mac. Anyway you can use wireshark or something like that to verify if the |
Hello there, I just came across the same issue on localhost Mac Monterrey v12.4 |
@le4onardo Unfortunately no, I have not. I haven't been able to look into it too deeply - I have just been using a live website for my project, to avoid localhost altogether. Would love to hear about any resolution you may find though, and I might have time in the next few days to look into it myself as well. |
I'm closing this. Discussion con continue in the closed thread if needed. |
Alright, I was on a plane and gave debugging this another shot. I found something pretty interesting. To see more clearly what is happening, I decided to just inject some code in the ws library. I injected this logic in the startLoop() function of receiver.js, at the beginning of the
So if I understand the code correctly, this will print out the raw bytes of every message the websocketserver receives post-upgrade. Super strangely, this is what I get on the first message sent:
... and then some binary data. As is obvious, this isn't the WS message binary - this is the initial HTTP request! This is why it says RSV1 must be clear. The first two bytes aren't what they are supposed to be, they are After that, I tried something else. I found that the number of bytes of the GET request is 497. So, at the beginning of startLoop(), before it enters the
And amazingly, the initial request actually worked now. I tried sending two messages back to back, and yet another interesting thing happened in my logs: On the first message log, I can see the GET request and the first message. On the second message log, I can see the GET request, the first message, AND the second message. I added a few more messages, and it started indeterminately failing at some point after the first message. So what it seems like is happening is that somehow, the buffer that the receiver is reading from doesn't flush after being read or something? So it reads from the beginning of the sockets history multiple times. This sounds like it could be any one of these things:
Do you have any suggestions on how I could continue investigating this further? Thanks so much! |
Use tcpdump or wireshark and see the actual data that is sent by the client. |
Okay, finally did that. I used tcpdump to capture this browser code:
So, simply opening the connection and sending a single message. The results of the tcpdump:
So, this seems pretty definitive that the client is somehow sending the GET request again with the first WebSocket message. |
Filed a Chromium bug here: https://bugs.chromium.org/p/chromium/issues/detail?id=1421590 Perhaps they will be able to reproduce, and dig into it further. |
@timschwab any update on this? I am currently seeing this exact behaviour on chrome client but also on a node client? so its not related to chromium in my case. |
@mattvb91 Hey, I did eventually find a solution - use a port other than 8080. I still don't know why that port did not work, while others did. My theory is that Mac Docker was doing something weird with it that caused it to exhibit the behavior I found above, but once I found I could simply switch ports, I stopped investigating. |
Also just to close the loop, my post on the Apple dev forum is here: https://developer.apple.com/forums/thread/726731 |
thanks @timschwab for the response. In my case it seems to be with the express library. As soon as I went back to native http.createServer and the websocket server its working fine. |
Thanks @timschwab for pointing us in the right direction. Just as a reference for others you are banging their heads on this issue. We had a similar issue and it turned out to be the Parental Control was enabled on the laptop which hijacked port 8080 (https://discussions.apple.com/thread/250500940). Conclusion: don't use 8080 on mac osx... |
I reclaimed port 8080 by going to System Settings > Screen Time > Content & Privacy. macOS 15.3.1 |
Is there an existing issue for this?
Description
There are a few other issues for this, but it seems that in all of them, the answer has been, "The client sent bad data, so the error is expected." However, after doing some testing with several standard web browsers, unless I am missing something very basic, this is difficult to believe.
My server code is dead simple:
I've opened the JS console in Chrome, Safari, and Firefox and typed these three commands with identical results:
sock.extensions
is empty, but the logging results on the server are:So I just want to clarify that all three of these browsers on Mac have a bad websocket implementation? Or am I missing something fundamental?
ws version
8.11.0
Node.js Version
v17.1.0
System
System:
OS: macOS 13.0.1
CPU: (4) x64 Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz
Memory: 50.64 MB / 8.00 GB
Shell: 5.8.1 - /bin/zsh
Expected result
A message from a standard browser's WebSocket implementation would function properly
Actual result
Each browsers caused an error in the
ws
libraryAttachments
No response
The text was updated successfully, but these errors were encountered: