Connect manually with sails.io.js - node.js

I'm trying to use sails.io.js in a chrome extension.
I'm setting manually the url of my sails server with the line :
io.sails.url = "http://localhost:1337";
But I would like to get the url from the chrome local storage (to save the url not directly in the code). But the problem is, as said here:
You get 1 clock tick after the import before the socket attempts to
connect.
So if I get the URL from the chrome local storage with :
storage.get('url', function(result){
var url = result.url;
io.sails.url = url ;
});
It's too late! The options must be set just after the sails.io.js code..
So I was thinking about disabling autoConnect with :
io.sails.autoConnect = false;
(As said there)
But now my question is : How can I can connect manually with io.sails ?
I've tried io.sails.connect(), did not work. Any ideas ?
Thank you very much,

Well, it's yours to customize but if you want to get away with minimal amount of changes to sails.io.js then you could
change setTimeout to io.sails.doit = function() {
throw away the io.sails.autoConnect check
call io.sails.doit(..) when you're ready
Also, if you want to pass something over during the handshake you can add {'query':'param='+value} as second argument to io.connect(io.sails.url);
It is then available in sails app's config/sockets.js through socket.handshake.query.param.

Related

Save state of TCP socket (connection) after page refresh

I'm building a node.js & express app that connects to an IoT device over TCP. On the index page of the app I am rendering the page and running a function that starts to ping the device. Eventually the device responds, I open a TCP socket, and I use socket.io to emit an event to the front end. This process takes much longer than the time to render the page.
When I refresh the page, I do not want to re-ping the device. I need to "save" the state of the connection. Knowing that the device is already connected, I should not need to re-run my connection function.
Possible solutions. My thoughts:
Boolean variable for TCP socket status. In the node.js net documentation I do not see a variable for socket connection status. Another stackoverflow answer said ._connected is undocumented and could work but 'this is not the node.js way'.
Sessions. I could save device state in a session, and keep track of it on re-load. However, based on my reading I can't save the session information after the res.render is called. I specifically want to save the connection status after reload.
Use a local variable. However this is 'reset' on page load.
Save state in JSON file. Use a separate deviceState.js file with state information. I could export that file and use it as a required module in my index page.
My question is - how can I save the state of the device connection even when the page is reloaded? My hunch is there is some combo of session and local variable but I am not sure how these could work based on my points above.
Here's a simplified version of the index route. Let me know if it is missing anything that would help solve this problem:
router.get('/', function(req, res, next) {
function connectToDevice() {
// ping device and open TCP socket...
// eventually the following function is called as an eventlistener to
// a net socket.on('connect')...
function onConnect(socket) {
res.io.emit('machine-online');
}
}
connectToDevice();
res.render('index', {
title: 'Page title'
});
}
This is my first time posting on stackoverflow. I am still learning the relevant key words and have been unable to find a solution to this problem.
The way I solved this is #4, save state in external JSON.
deviceStatus.js: File at the root of the app structure that holds some information in JSON object.
var status = {};
var deviceStatus;
deviceStatus = function() {
status = {
"isOnline": false,
};
return status;
};
module.exports = deviceStatus();
Then in my index.js: Require the deviceStatus module.
var status = require('../deviceStatus');
And I am using this to render the page: In the (not shown) connectToDevice() function, I set status.isOnline == true. So here, if the device is offline, then I connect and render the page. If not, only render the page, do not connect.
if(status.isOnline == false) {
connectToDevice();
}
res.render('index', {
title: 'Page title',
machineOnline: status.isOnline
});
There might be a better way to do this, but this is the method that works for me. When the app re-loads the status.isOnline starts as false, which works since it is not connected yet.

Transport Settings in Socket.IO 1.4.x

I have been tinkering with deployd on Heroku using this gist as a starting point:
https://gist.github.com/facultymatt/5373247
Line 20 of that server.js tries to set transports for socket.io like so:
server.sockets.manager.settings.transports = ["xhr-polling"];
But encounters this error:
Cannot read property 'settings' of undefined.
From research so far it seems this approach is deprecated in socket.io 1.4.5. However, if that's so I am not clear on how I should address this setting.
My question is similar to this one. But differs in that I seek to change the settings once socket.io is already constructed by and attached to an instance of deployd.
Set it on creation:
var server = deployd({
socketIo: {
options: { transports : ['xhr-polling'] }
}
});
Or if you can't do that, change it runtime (this is a hack):
server.sockets.server.eio.transports = ['xhr-polling'];
(This is still supported for backwards compatibility:)
server.sockets.server.set('transports', ['xhr-polling']);

Get windows client username in Nodejs

I am developing a little application in nodeJS and AngularJS. all my clients are windows machines, and they are all in the same domain.
I want to add some text label in the page like " Welcome ! USERNAME" .
how can get the Windows username of the client when he gets homepage?
I read about passport and node-sspi, but didnt understand how to implement that.
thank you :)
Stackoverflow user 'azium', explains in this response that
"AngularJS is a client side application and only has access to the
variables that are delcared (sic) in the browser's window object. The
Environment object is something that is only accessible on the server
by default."
However, according to Arhsim Tima you can try the following javascript,
For IE:
var objUserInfo = new ActiveXObject("WScript.network");
document.write(objUserInfo.ComputerName+"<br>");
document.write(objUserInfo.UserDomain+"<br>");
document.write(objUserInfo.UserName+"<br>");
var uname = objUserInfo.UserName;
alert(uname);
For Firefox:
function getUser() {
return Components.classes["#mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment).get('USERNAME');
}

How to catch when a user leaves the page in Meteor and/or Iron router?

I'm trying to catch when a user leaves from my Meteor application (version 1.2.0.2) ; something equivalent to the SocketIO disconnect() on the server side.
The user could close his browser, go to another website or simply refresh the page and it would fire anyway
Surprisingly, i'm searching on Internet and everything is mixed up, nothing works properly. I thought Meteor was literally based on this magic-live processing so it must manage this event in a way or another.
Iron router documentation specify this :
onStop: Called when the route is stopped, typically right before a new
route is run.
I also found Router.load and Router.unload but none of them work. This is my current [not working] code which is quite simple
Router.configure
layoutTemplate: 'MasterLayout'
loadingTemplate: 'Loading'
notFoundTemplate: 'NotFound'
Router.onStop (->
console.log('Try to stop')
Users.insert({
name: "This is a test"
lat: 0
lng: 0
})
)
Am I doing something wrong here ? How do you catch this event in my app ?
You need to attach to the onStop of the route, not the router. For instance:
Router.route('/', {
onStop: function() {
console.log("someone left the '/' route");
}
});
Another option is to use the onStop event of subscriptions. That is probably the option most similar to the socketio disconnect you mentioned. You can find an example of that in the typhone source code.
There were two solution working, I found the 2nd and best one by searching in the API Documentation for a while.
First solution : working with subscribe & publish
Anywhere in the controller / front-end side you must subscribe to a collection
# in coffee
#subscribe('allTargets')
# in javascript
this.subscribe('allTargets')
Afterwards you just have to publish and add a onStop listener. This example will take a Targets collection I already defined somewhere before, it just gets all the entries.
# in coffee
Meteor.publish 'allTargets', ->
#onStop ->
# Do your stuff here
return Targets.find()
# in javascript
Meteor.publish('allTargets', function() {
this.onStop(function() {
// Do your stuff here
});
return Targets.find();
});
You have to be careful not to return Targets.find() before you set the onStop listener too. I don't think it's a perfect solution since you don't listen to the connection itself but the changes of a collection.
Second solution : working with DDP connection
I realized through the Meteor API Documentation we can directly listen to the connection and see if someone disconnect from the server-side.
To stay well-organized and clean within my Meteor Iron project I added a new file in app/server/connection.coffee and wrote this code
# in coffee
Meteor.onConnection (connection) ->
connection.onClose ->
# Do your stuff
# in javascript
Meteor.onConnection(function(connection) {
connection.onClose(function() {
// Do your stuff
});
});
You can manage datas with connection.id which's the unique identifier of your browser tab. Both solutions are working well for me.
If you use Meteor.userId through their accounts system, you can't use it outside a method in the server-side so I had to find a workaround with the connection.id.
If anyone has a better solution to manage connections while getting this kind of client datas, don't hesitate to give your input.

Websocket server running fine but cannot connect from client (what url should I use?)

OK this is very simple to anyone who's used websocket and nodejs.
I have created a websocket server named ws_server.js and put it in C:\Program Files (x86)\nodejs where I have installed the nodejs framework. I started the server and it is running and it says it's listening on port 8080. So far so good, I have the server running.
Now I simply want to connect to it from client code so that I can do all that lovely stuff about capturing events using event listeners etc. The problem is, embarassingly, I cannot figure out what URL to use to connect to my websocket server.
function init() {
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket("ws://localhost:8080/"); // WHAT URL SHOULD BE USED HERE?
websocket.onopen = function(evt) { alert("OPEN") };
websocket.onclose = function(evt) { alert("CLOSE") };
websocket.onmessage = function(evt) { alert("MESSAGE") };
websocket.onerror = function(evt) { alert("ERROR") };
}
function doSend(message) {
// this would be called by user pressing a button somewhere
websocket.send(message);
alert("SENT");
}
window.addEventListener("load", init, false);
When I use ws://localhost:8080 the only events that trigger are CLOSE and ERROR. I cannot get the client to connect. I must be missing something very simple. Do I need to set up my nodejs folder in IIS for example and then use that as the URL?
Just to reiterate, the websocket server is running fine, I just don't know what URL to use to connect to it from the client.
EDIT: The websocket server reports the following error.
Specified protocol was not requested by the client.
I think I have got it working by doing the following.
var websocket = new WebSocket("ws://localhost:8080/","echo-protocol");
The problem being that I needed to specify a protocol. At least now I get the onopen event. ...if nothing much else
I was seeing the same error, the entire web server goes down. Adding the protocol fixes it but leaves me wondering why it was implemented this way. I mean, one bad request should not bring down your server.
You definitely have to encase it a try/catch, but the example code provided here https://www.npmjs.com/package/websocket (2019-08-07) does not. This issue can be easily avoided.
I just wanted to share a crazy issue that I had. I was able to connect to a websocket of an old version of a 3rd party app in one computer, but not to a newer version of the app in another.
Moreever, even in new computer with the new version of the app, The app was able to connect to the websocket, but no matter what I did, when I tried to connect with my own code, I kept getting the error message that the websocket connection failed
Long story short, They changed an apache configuration that allowed connecting to the websocket via a proxy.
In the old version, apache config was:
ProxyPass /socket/ ws://localhost:33015/ retry=10
ProxyPass /socket ws://localhost:33015/ retry=10
In the new version, apache config was changed to:
ProxyPass /socket/ ws://localhost:33015/ retry=10
By bad luck, I was trying to connect to ws://localhost/socket and not to ws://localhost/socket/. As a result, proxy was not found, and connection returned an error.
Moral of the story: Make sure that you are trying to connect to a websocket url that exists.
For me, the solution was to change the URL from ws:// to wss://. This is because the server I was connecting to had updated its security, and now only accepted wss.

Resources