I'm trying to connect as a socket client to a socket server with this code:
let socket = new WebSocket('wss://' + serverConfig['host'] + ':' + serverConfig['port'] + '/some/uri', {
perMessageDeflate: false,
rejectUnauthorized: false, // Server is self-signed for reasons.
});
In this specific instance, the host is 192.168.0.57 and the port is 443. Unfortunately, it throws this error:
Error: unexpected server response (200)
at ClientRequest._req.on (/var/www/html/node_modules/ws/lib/WebSocket.js:650:26)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:188:7)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:473:21)
at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
at TLSSocket.socketOnData (_http_client.js:362:20)
at emitOne (events.js:96:13)
at TLSSocket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at TLSSocket.Readable.push (_stream_readable.js:134:10)
This is baffling, since I'm basically being told that it's an error that the response was OK. I hope there's something wrong with my request, but the error message is utterly uninformative.
Your server is not handling the handshake properly. It answers to the upgrade request as it was a normal request. Make sure that you are hitting the WebSocket server.
I got it working by switching libraries. I don't think there's anything wrong with this one, just some other piece to my larger puzzle. I hate to close this without a full explanation. Thanks!
I have a similar (if not the same) problem. I copied the express example code from the README and made the following modification:
const cors = require('cors');
app.use(cors());
In the client I have these lines:
import WebSocket from 'ws';
const connection = new WebSocket('ws://localhost:8080');
The browser throws the following error:
> Uncaught (in promise) Error: unexpected server response (200) WebSocket.js:650
When skipping the import Websocket from 'ws' part in the browser, thus relying on the native websocket, it works as expected.
I sure shall be missing something... can you spot it?
@creimers can you show us your server code?
@lpinca Sure!
Like I said, it's almost exactly the express example from the README.
I got express==4.15.2 and ws==2.3.1 installed.
const express = require('express')
const http = require('http')
const url = require('url')
const WebSocket = require('ws')
const cors = require('cors')
const app = express();
app.use(cors())
app.use(function (req, res) {
res.send({ msg: "hello" });
});
const verifyClient = (info) => {
console.log('ding dong')
return true
}
const server = http.createServer(app);
const wss = new WebSocket.Server({ server, verifyClient });
wss.on('connection', function connection(ws) {
const location = url.parse(ws.upgradeReq.url, true);
// You might use location.query.access_token to authenticate or share sessions
// or ws.upgradeReq.headers.cookie (see http://stackoverflow.com/a/16395220/151312)
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
server.listen(8080, function listening() {
console.log('Listening on %d', server.address().port);
});
@creimers it works on my machine. Tested with this client code:
var WebSocket = require('ws');
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
ws.send('foo');
};
ws.onmessage = function (evt) {
console.log(evt.data);
};
@lpinca Thanks for looking into it. I still can't get it to work here...
Can you show your complete client code?
Additionally, webpack gives me this error:
Warning in ./~/bindings/bindings.js
Critical dependencies:
76:22-40 the request of a dependency is an expression
76:43-53 the request of a dependency is an expression
@ ./~/bindings/bindings.js 76:22-40 76:43-53
@creimers that is the complete client code. In the browser you have to use the native WebSocket object. Add a shim like this:
var ws;
if (typeof WebSocket !== 'undefined') {
ws = WebSocket;
} else if (typeof MozWebSocket !== 'undefined') {
ws = MozWebSocket;
} else {
ws = window.WebSocket || window.MozWebSocket;
}
module.exports = ws;
and in your package.json add
"browser": {
"ws": "./ws-browser.js"
}
I have to be honest: I have no idea what's going on.
I'm on the latest Chrome. If on the client I'm using the native WebSocket object, then what is the require('ws') for?
Maybe it's all a big misunderstanding. It seemed to me that ws could also be used in the browser, providing enhanced features such ass passing headers and such, as documented here.
No, ws can not be used in the browser as there is no way to have access to a raw TCP socket in the browser via JS.
The require('ws') and the shim allow you to use the same code for both the browser and Node.js so you have to write your client code only once.
@lpinca Thanks for clarifying.
Anyway I'm not sure why the server answers with 200 to the upgrade request in your case. It doesn't make sense.
I have the same error...
hey @creimers did you fix the error or just use the native websocket in the browser with the shim code?
@zh0uquan in the browser you must (https://github.com/websockets/ws/issues/1093#issuecomment-300717475) use the native WebSocket object. I think the error comes from the fact that the browserified ws can not send upgrade requests. I guess the the http module is replaced with the Fetch or XMLHttpRequest API.
The server answers as it was a normal request, thus the error.
Makes sense?
has someone fixed the issue?
maybe you can try it:
location / {
proxy_pass http://127.0.0.1:3030;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
nginx config
done!
just remove the following line
const WebSocket = require('ws');
in browser code and you will be happy.
same error. wasted time
also getting this error:
unexpected server response (503)
Most helpful comment
I got it working by switching libraries. I don't think there's anything wrong with this one, just some other piece to my larger puzzle. I hate to close this without a full explanation. Thanks!