How to set connection id in SignalR client? - javascript

I need to set connection id before hubConnection.start();
I look here https://github.com/SignalR/SignalR/wiki/SignalR-JS-Client and what i found:
connection.id - Gets or sets the client id for the current connection.
Tried this. No working. Here is the client code:
let hubUrl = 'http://localhost:5000/chat';
let hubConnection = new signalR.HubConnectionBuilder()
.withUrl(hubUrl)
.configureLogging(signalR.LogLevel.Information)
.build();
hubConnection.id = "12345";
hubConnection.on("Send", function (data) {
let elem = document.createElement("p");
elem.appendChild(document.createTextNode(data));
let firstElem = document.getElementById("chatroom").firstChild;
document.getElementById("chatroom").insertBefore(elem, firstElem);
});
document.getElementById("sendBtn").addEventListener("click", function (e) {
let message = document.getElementById("message").value;
hubConnection.invoke("Send", message);
});
hubConnection.start();
hubConnection.id = "12345"; this do not change real connection id.
And maybe you are know some other way how to write client-side connection?

The connectionId can't be manually created or manipulated at all and it is created during negotiation request with the server. You can read here that you can implement your own IConnectionIdFactory but it is not recommended to do that. Maximum what you can do is get the connectionId and use it for mapping users and groups and other logic inside your hub.

Related

How to send custom headers in websocket creation in javascript?

So I had the following code on Python that created a websocket connection:
channels_dict = {}
channels_dict['Authorization'] = 'true'
for channel in channels: #adds some extra headers with info
channels_dict["Channel" + str(channel)] = '1'
ws = websocket.WebSocketApp("ws://localhost:8888/ws",
on_message = on_message,
on_error = on_error,
on_close = on_close,
header = channels_dict)
And I could easily add extra headers that I could access later in the server upon connection. Is there a way I could do the same in Javascript? I haven't found much information about setting custom headers in websocket creation. I have the following code in JS:
var webSocket;
function openWebsocket() {
webSocket = new WebSocket("ws://localhost:8888/ws")
}
I've heard of adding query parameters in the url, is that the only way of adding extra headers/information to a websocket connection in javascript?
Try this:
const webSocket = new WebSocket ("ws://localhost:8888/ws" + "?param1=" + param1); // here you can add other params
webSocket.on("open", function open(e) {
console.log("*** websocket opened");
});

NodeJS Websocket use variable in HTML (with express?)

I have been searching for two days now looking for a solution that might work for me. Sadly I have only seen examples and guides on how to setup a websocket server (that sends messages back and forth to clients) and a websocket client (that resides in browser). None of these really work for me, and I am not sure how to achieve what I want here.
Basically I have the following websocket:
require('dotenv').config()
const WebSocket = require('ws');
var connection = new WebSocket('ws://XXX');
connection.onopen = function () {
connection.send(JSON.stringify({"authenticate":process.env.API}));
connection.send(JSON.stringify({"XXX":"YYY"}));
connection.send(JSON.stringify({
"db" : "unique_id",
"query" : {
"table" : "users"
}
}));
};
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
var myResponse = JSON.parse(e.data);
var qList = myResponse.results;
};
What I want to do is have my nodeJS-script running, for example an express script with a html page, that also includes the response from onmessage. Why I am complicating this instead of just using the websocket client-side is that I cannot send my auth-code publicly.
Hope I have been clear enough, let me know if you are unsure of my question!
PS. If you think I would be better off using another websocket-script such as Socket.io - I have been looking at them and have not gotten much wiser sadly.
You have a lot of options. Probably the easiest is to export the connection. At the bottom of the file, e.g. module.exports = connection
Then in the express application, import the connection, e.g. const connection = require('./path/connection');
Then make a function that calls itself at a given interval and sends the appropriate message.
Then within the Express app you can use something like connection.on('message', (data, flags) => // do stuff);
Your other option is to create a store object. E.g.
// ./store.js
class store {
constructor() {
this.wsMaterial = {};
}
add(wsInfo) {
this.wsMaterial[key] = wsInfo
}
get store() {
return this.wsMaterial
}
}
module.exports = new store()
Then import the store and updated it, e.g.
// ./websocket file
const store = require('./store');
...
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
var myResponse = JSON.parse(e.data);
var qList = myResponse.results;
store.add(qList)
};
Then from Express...
// ./express.js
const store = require('./store');
store.get // all of your stuff;

Net.Socket instances don't go away in NodeJS

I'm trying to recreate the functionality of a hardware serial server with Node and it's actually working, but I'm getting errors from socket instances that have been closed.
Here's a simplified version of the app to show what I'm doing...
var net = require('net');
var SerialPort = require('serialport');
var connectionCounter = 0;
var port = new SerialPort('/dev/ttyUSB0', function () {
var server = net.createServer();
server.on('connection',function(socket) {
connectionCounter++;
var connNumber = connectionCounter;
socket.on('error', function () {
console.log('socket ' + connNumber + ' errored');
});
socket.on('data', function(data) {
port.write(data);
});
port.on('data', function(data) {
socket.write(data);
});
});
server.listen(8887, '127.0.0.1');
}
});
So the first chunk of code that's sent into the 8887 port works fine, and it returns the data back out through the socket. The errors start on the second chunk. In the example, I'm keeping a count of the socket instances and outputting the socket instance number with the error. So as the program runs, the number of sockets instances keeps going up. The most recent instance will eventually handle the data, but I can't figure out what I need to delete to clean up all of the previous socket instances so they'll stop trying to process the incoming data.
I've tried socket.end() and socket.destroy(), but those don't seem to work . Do I need to go as far as deleting the server itself and recreating it?
If anyone ever finds this and cares about what was going wrong, I was setting an event listener on the serialport object every time a new net socket was created. So even though I was deleting the socket every time it was closed, the serialport listener was trying to send data to all of the old deleted sockets. So the solution was to removeListeners from the serialport object upon closing the net socket.
you can use array for storing sockets later on you can delete. this is sample code hope you got the idea
var net = require('net');
var SerialPort = require('serialport');
var connectionCounter = 0;
var mySockets = [];
var port = new SerialPort('/dev/ttyUSB0', function () {
var server = net.createServer();
server.on('connection',function(socket) {
mySockets.push(socket);
connectionCounter++;
var connNumber = connectionCounter;
socket.on('error', function () {
console.log('socket ' + connNumber + ' errored');
});
socket.on('data', function(data) {
port.write(data);
});
port.on('data', function(data) {
socket.write(data);
});
});
server.listen(8887, '127.0.0.1');
}
//get the sockets you want to delete
var s = mySockets.pop();
s = null;
});

SignalR javascript client not picking up event from hub

I have a method on the hub however I am not getting any messages from this. I get the connection ID's from my user to connectionid mapping dictionary and loop through these connectionid's and then invoke a method on the client side called deviceDiscovered I can also confirm that the browser does connect to the hub
Here is my hub method
public async Task DetectDevice(dynamic message)
{
//We will be searching via the userid
var connectionId = Context.ConnectionId;
//now we get the connectionID from the table.
var connectionObj = ConnectionTable[connectionId];
//we now check whether this is a pathfinder or browser client
if (connectionObj.clientType == "pathfinder")
{
/*The pathfinder initiated the request and so this means the message should be forwarded to the browser client
that requested this resource*/
//Grab the data out of the dictionary.
PathfinderDetection deviceDiscoveredNotification = JsonConvert.DeserializeObject<PathfinderDetection>(message);
var userId = deviceDiscoveredNotification.userId;
var sysInfo = deviceDiscoveredNotification.sysInfo;
var found = deviceDiscoveredNotification.data;
if (found == "FOUND")
{
var deviceId = deviceDiscoveredNotification.deviceID;
var connections = ConnectionTable.Where(val => val.Value.id == connectionObj.id).Select(key => key.Key).ToList();
foreach (string connection in connections)
{
Clients.Client(connection).deviceDiscovered(deviceId);
}
}
else
{
//call a method on client side.
Clients.Group(userId.ToString()).noDevice("NOTFOUND");
}
I can see that the deviceID variable is populated and that the connection exists, however not getting anything back from the hub when looking at the client
here is my client side code:
<script>
$(document).ready(function(){
var connection = $.hubConnection("http://localhost:59016");
var contosoChatHubProxy = connection.createHubProxy('metrics');
contosoChatHubProxy.on('taskAdded', function(data){
console.log(data);
});
contosoChatHubProxy.on('deviceDiscovered', function(data) {
console.log(data);
});
contosoChatHubProxy.on('taskUpdate', function(data){
console.log(data);
});
contosoChatHubProxy.on('noDevice', function(found) {
console.log(found);
});
});
</script>

Socket.io: How to uniquely identify a connection on client and server?

My app supports multiple socket.io clients from the same host (IP address). For diagnostics, I need to be able correlate client and server logs to identify which client the server is talking to. Does socket.io provide a way to uniquely identify a connection?
What I do is that within /routes/socket.js, I have these added to my requires:
var thisApp = require('../app');
var cookieSig = require('express/node_modules/cookie-signature');
var cookie = require('cookie');
var connect = require('express/node_modules/connect')
, parseSignedCookie = connect.utils.parseSignedCookie;
This answer assumes you have a session store of some kind that you can access via thisApp.thisStore. In my case, in the main app.js, I set up a session store using kcbanner's connect-mongo (available via npm and github.com) using a MongoDB back-end hosted on MongoLab for mine. In the session store, for each session, you can have a unique username, or some other identifier that goes along with that session. Really, you can tack any data you want to that session. That's how you'd tell them apart.
The code I use looks like this:
module.exports = function (socket) {
socket.on('taste:cookie', function (data, callback) {
console.log("taste:cookie function running");
//get the session ID
var sid = data.sid;
sid = parseSignedCookie(sid['connect.sid'], "mySecret");
console.log("sid: ",sid);
//get the handshake cookie
var hssid = cookie.parse(socket.handshake.headers.cookie);
hssid = parseSignedCookie(hssid['connect.sid'], "mySecret");
console.log("hssid: %s",hssid);
if(sid) {
if(sid['connect.sid']) {
sid = sid['connect.sid'].slice(2);
console.log("sliced the sid: %s",sid);
sid = cookieSig.unsign(sid, "mySecret");
hssid = sid;
}
if(hssid != sid) {
console.log("browser cookie not set right; rectifying...");
data.sid = hssid;
sid = hssid;
}
else console.log("browser cookie was set right");
}
thisApp.thisStore.get(sid, function(err, gotsession) {
if(err || !gotsession) {
//handle error
return;
} else {
if(gotsession.username) {
callback(0, {username:gotsession.username});
}
else callback(1, {username:""});
}
});
});
Maybe there's a more elegant way to do this, but this does work.
You can use session+cookies: Here's a library that you can use or learn from: session-socket.io.
You'll find plenty of examples on their README page.

Categories

Resources