There seems to be a lack of information about how we can get a socket identifier. the reason for this is as your example shows there should be an authentication system. but then I need to save information about that authentication into my application.
E.G
Client Connection (socket)
Authentication (App) - needs to save what they are authenticated for
Server Upgrades / Accepts
I tried saving information against the socket E.G
on('connection', (sock) => { sock.id = "something"; })
on('close', (sock) => {console.log("Socket closing", sock.uuid);})
If there is a method could it be documented, if there's not would it be possible to provide some method so it could be E.G a socket identifier against the socket on connection or reconnection?
[x] I've searched for any related issues and avoided creating a duplicate issue
Not really :)
This is out of the scope of the project and if you search through the closed issues there are multiple suggestions on how to do this. You can add an ID to the Websocket object as show in your example and/or keep a map ID -> websocket.
I'm sorry but socket identifier is out of the scope of this project, then close the project because the whole point about WebSockets is to give a TCP like a stack (so clearly this is not a web socket implementation its a hash up), every TCP socket system implemented gives a way to identify the socket, you said my example works but it does not so clearly that's a bug because as my example says it does not work the console.log gives an undefined.
Hell, a socket in its own right is an identifiable thing because it binds to a unique port on the server. You have the listener on a port, then as soon as a connection is made to the listener and it promotes to a socket the server then gives it it's own port also known as a socket.

const WebSocket = require('ws');
const SocketHandler = require('./src/SocketHandler');
const wss = new WebSocket.Server({
port: 8080,
perMessageDeflate: {
zlibDeflateOptions: {
chunkSize: 1024,
memLevel: 7,
level: 3
},
zlibInflateOptions: {
chunkSize: 10 * 1024
},
clientNoContextTakeover: true,
serverNoContextTakeover: true,
serverMaxWindowBits: 10,
concurrencyLimit: 10,
threshold: 1024
}
});
wss.on('connection', SocketHandler.openConnection);
From the RFC for Websockets:
An identifier for the service provided by the server. If the server provides multiple services, then the value should be derived from the resource name given in the client's handshake in the "Request-URI" [RFC2616] of the GET method. If the requested service is not available, the server MUST send an appropriate HTTP error code (such as 404 Not Found) and abort the WebSocket handshake.
I'm not sure what you are talking about.
const uuid = require('uuid');
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 0 });
server.on('connection', function(ws) {
ws.id = uuid.v4();
console.log('open', ws.id);
ws.on('close', function() {
console.log('close', ws.id);
});
ws.close();
});
server.on('listening', function() {
const { port } = server.address();
const ws = new WebSocket(`ws://localhost:${port}`)
});
Run this and you'll see that it works as expected.
Section 4.2.2 of the RFC describes the server's opening handshake and has nothing to do with what you want. It's what the server should verify and return in the HTTP response sent to the client.
yeah,
And as part of that opening handshake, there is a socket identifier used that identifier gives it a unique match to the socket, so it should be exposed so applications can use it to know what socket is sending what and if it is actually allowed to do it.
The example I have given built from your #859 issue before I opened this ticket, does not work and I have shown in VSCode does not work line 12 of the print screen, then look at the bottom 3 lines of the terminal (it does not even save to the object properly i don't know if this is a regression because of rules put on the object but it does not work) .
You code,
wss.on('connection', (ws) => {
ws.id = uuid.v4();
});
Does not work!!! as my screen shot shows.
The fact is the library must have some way of knowing a socket Identifier otherwise it could not send messages to a socket, all I'm asking for is that identifier to be made public to the socket (and the documentation says how to get it). and if that's too hard just a two-method and a var to the object E.G setPublicIdentifer(string id); getPublicIdentifer().
The fact is without a way to identify a socket how in the hell does one know what the socket is authorised to do E.G if it tries to send something that would change something when they are not authorised to do so. the point is one server many clients, and clients can have different permissions and there needs to be a method to save what permissions each client has on the server.
Using your own code:
const uuid = require('uuid');
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 0 });
const SocketHandler = (new function SocketHandler() {
this.openConnection = (sock) => {
sock.id = uuid.v4();
sock.on('close', this.closeConnection.bind(this, sock));
console.log('Socket assigned uuid', sock.id);
}
this.closeConnection = (sock) => {
console.log('Socket closing', sock.id);
}
});
server.on('connection', SocketHandler.openConnection);
server.on('listening', function() {
const { port } = server.address();
const ws = new WebSocket(`ws://localhost:${port}`);
ws.on('open', ws.close);
});
$ node index.js
Socket assigned uuid 983f1544-874b-423b-95d2-7674a6fc614e
Socket closing 983f1544-874b-423b-95d2-7674a6fc614e
Well, it's not working for me, so what's different,
edit found the problem
Your are not using my code you changed my code overwriting the value of sock in the closeHandler
this.closeConnection.bind(this, sock)
You're overwriting the state of the socket in closeConnection with the socket from openConnection not the socket from the WebSocket systems close handler. so if something happens to the socket inside WebSocket before the close method, the bound method will be unable to see that change. because you're overwriting it with the old state.
E.G
This is horrendous practise in Javascript and has been since IE6 your killing a newer state to get data from the old state not adding it to the object for it to stay persistent through all states.
end of edit
I'm running node 14 (current) and it does not work.
Is this because of node 14 perhaps some new security around objects I don't know but it's not working as you can see in my screenshot it saves against the object for debugging but I'm completely unable to read it out?
here is a pull request that fixes it, it's due to class / object security as an object of a class in javascript can't have its persistent state updated from outside the class/objects methods without it being handled or internally supported by the class/object
https://github.com/websockets/ws/pull/1751
server.on('connection', (sock) => {
console.log("Socket Connected");
sock.id = uuid.v4();
console.log("Socket assigned uuid", sock.id);
sock.on("close", function(){ console.log(this.id); });
});
I would say this is a code only fix if you wish to create tests you can, and please update the read me as to show this is supported.
it's due to class / object security as an object of a class in javascript can't have its persistent state updated from outside the class/objects methods without it being handled or internally supported by the class/object
It doesn't make much sense. JavaScript allows you to add any property to an object.
class Foo {}
const foo = new Foo();
foo.id = 123;
console.log(foo.id); // => 123
this.closeConnection.bind(this, sock);
this is needed because your this.closeConnection() takes a sock argument but is used as a listener for the 'close' event. The listeners of the 'close' event only take two arguments. The close code, and the reason, not the WebSocket instance.
I suggest you read the EventEmitter documentation and this in particular https://nodejs.org/api/events.html#events_passing_arguments_and_this_to_listeners.
Also read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this. The this keyword works differently from other languages.
It's because when an event is called the scope of this is the object the event is being called on E.G
obj.emit('evntName') call the eventName with this defined as obj automatically by JavaScript.
So the closeHandler should have access to WebSocket via this, but because it did not work in my testing i tried looking for sock to be passed in.
This all happens because sock of type WebSocket is created within the scope of WebSocketServer, so nothing from outside that scope can change it, scopes are a hierarchy of privileges. the owners can affect change the scope it's self can affect change by remote code can't.
I have read them that's the point can't save persistent data on the object from outside its creation scope. and I am well aware of what this does in javascript and what it does not do. i have been programming javascript since IE6 where this was primarily used only to effect HTML objects via events bound to them.
that's the point can't save persistent data on the object from outside its creation scope.
This is not true.
Anyway I've tried to help you and spent quite a bit of my free time here. I'm done, if you don't like the lib and think you can make it better please fork it and use your own fork.
okies, done that, https://www.npmjs.com/package/better-web-sockets#obtaining-socket-identifyer
Most helpful comment
Anyway I've tried to help you and spent quite a bit of my free time here. I'm done, if you don't like the lib and think you can make it better please fork it and use your own fork.