Embedded node-red in a feathersjs application get websocket error - websocket

I can embed node-red with a custom service with the following node-red.service.js :
// Initializes the `node-red` service on path `/red`
const { NodeRed } = require('./node-red.class');
const hooks = require('./node-red.hooks');
const RED = require("node-red");
module.exports = function (app) {
const paginate = app.get('paginate');
const options = {
paginate
};
// Create the node-red settings object
const settings = {
httpAdminRoot:"/red",
httpNodeRoot: "/red",
userDir: "./red",
functionGlobalContext: { } // enables global context
};
// Initialise the runtime with a server and settings
RED.init(app,settings);
// Serve the editor UI from /red
app.use('/red' , RED.httpAdmin );
RED.start()
};
If I go to localhost:3030/red I get the node-red page, but after few seconds it lost connection to server with the following error:
WebSocket connection to 'ws://localhost:3030/red/comms' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
I think there is a problem serving thru websocket or maybe since /red/comms is not defined in feathersjs it can't connect. Any idea?
Thank you

The issue comes with this line:
// Initialise the runtime with a server and settings
RED.init(app,settings);
As the comment says, you need to initialise the runtime with a server object. Here you are passing it an Express application, not a server.
It is not possible to mount websocket listeners on an express app - Node-RED needs access to the underlying HTTP Server object.
I am not familiar with what apis featherjs provides, but it does appear to allow you access to the http server object - for example by calling app.listen yourself - https://docs.feathersjs.com/api/express.html#app-listen-port

Related

How do I connect to an Infura web socket in Ethers.js?

I know in Web3js you can connect to an Infura web socket like so:
const Web3 = require('web3')
const web3 = new Web3(
new Web3.providers.WebsocketProvider("wss://mainnet.infura.io/ws/v3/<project_id>")
)
but how do I connect using Ethers.js? I've tried searching the internet but the answer isn't immediately obvious.
Found it in the Ether.js docs:
const provider = new ethers.providers.WebSocketProvider(
"wss://mainnet.infura.io/ws/v3/<project_id>"
)
the mainnet is used by default, but you can specify also specify a test network:
// Using a test network
const provider = new ethers.providers.WebSocketProvider(
"wss://rinkeby.infura.io/ws/v3/<project_id>", "rinkeby"
)

Websocket connection. Why are we making a call to ws://echo.websocket.org?

I am writing some websocket code and I have this so far:
window.onload = function() {
// Get references to elements on the page.
var form = document.getElementById('message-form');
var messageField = document.getElementById('message');
var messagesList = document.getElementById('messages');
var socketStatus = document.getElementById('status');
var closeBtn = document.getElementById('close');
var socket = new WebSocket('ws://echo.websocket.org');
// Show a connected message when the WebSocket is opened.
socket.onopen = function(event) {
socketStatus.innerHTML = 'Connected to: ' + event.currentTarget.url;
socketStatus.className = 'open';
};
// Handle any errors that occur.
socket.onerror = function(error) {
console.log('WebSocket Error: ' + error);
};
form.onsubmit = function(e) {
e.preventDefault();
// Retrieve the message from the textarea.
var message = messageField.value;
// Send the message through the WebSocket.
socket.send(message);
// Add the message to the messages list.
messagesList.innerHTML += '<li class="sent"><span>Sent:</span>' + message +
'</li>';
// Clear out the message field.
messageField.value = '';
return false;
};
socket.onmessage = function(event) {
var message = event.data;
messagesList.innerHTML += '<li class="received"><span>Received:</span>' +
message + '</li>';
};
closeBtn.onclick = function(e) {
e.preventDefault();
// Close the WebSocket.
socket.close();
return false;
};
socket.onclose = function(event) {
socketStatus.innerHTML = 'Disconnected from WebSocket.';
socketStatus.className = 'closed';
};
};
What is this code doing:
var socket = new WebSocket('ws://echo.websocket.org');
What url is that? When I visit there with my browser it does not exist but it seems to be important as I can't simply jus replace that url with random strings. What does it do? Is Websocket an external API?
I'm looking at the network tab and I see this:
Request URL: ws://echo.websocket.org/
Request Method: GET
Status Code: 101 Web Socket Protocol Handshake
conceptually, what is going on? Why do I need to make a request to an external site to use Websockets?
echo.websocket.org provides a webSocket server that lets you make a webSocket connection to it and then it simply echos back to you anything that you send it. It's there primarily for testing and demo purposes.
The code you show looks like a demo/testing app designed to run in a browser web page for a webSocket connection which you can access something similar here: https://websocket.org/echo.html.
A URL starting with ws:// indicates a connection that intends to use the webSocket protocol.
What is this code doing:
var socket = new WebSocket('ws://echo.websocket.org');
It is making a webSocket connection to a webSocket server at echo.websocket.org.
What url is that?
That is a webSocket URL that indicates the intent to use the webSocket protocol to connect and talk to that host. This is not something you type in the URL bar of a browser. It's something that is used by a programming language (such as Javascript in your browser).
Is Websocket an external API?
It's a protocol that specifies a means of connecting, a security scheme, a packet data format, etc... You could say that the http protocol is to the webSocket protocol as the English language is to Japanese. They are different means of communicating. The specification for the webSocket protocol is here: https://www.rfc-editor.org/rfc/rfc6455.
It's also designed to fit well into the http/browser world and to be friendly with infrastructure that was originally designed for http requests. Just searching for "what is websocket" on Google will turn up all sorts of descriptive articles. The Wikipedia page for webSocket provides a pretty good overview.
There is tons written on the web about what the webSocket protocol is and is useful for so I won't repeat that here. You can see a tutorial on webSocket clients here and a tutorial on webSocket servers here.
In a nutshell, it's designed to be a long lasting, continuous connection (supported in all modern browsers) that allows a client to connect to a server and then maintain a continuous connection for (potentially) a long duration. While that connection is open, data can be easily sent both ways over the webSocket. The primary reason people use it is when they want the server to be able to send data directly to the client in a timely fashion without making the client continuously ask the server over and over again if it has any new data. Once a webSocket connection is established, the server can just "push" data to the client at any time.
I'm looking at the network tab and I see this. Conceptually, what is going on?
Request URL: ws://echo.websocket.org/
Request Method: GET Status Code:
101 Web Socket Protocol Handshake
Those are the first steps of establishing a webSocket connection. You can see a more complete description of how that connection works here: How socket.io works. That post talks about socket.io which is another layer built on top of webSocket, but the underlying protocol is webSocket.
Why do I need to make a request to an external site to use Websockets?
A webSocket's purpose is to connect a client to a server (so data can then be sent between them) so it would only be used when connecting to some server somewhere.

I don't get the $.connection.[hubName]

I try to add web socket functionality using signalR, based on :
the chat example.
I have 2 different project -
1: is pure server, includes web api:
I have a web method to get the request and call to hub:
[HttpGet]
[Route("api/GetData")]
public IHttpActionResult GetCorpDataApi()
{
return Ok(getResponse());
**startWebSocket();**
}
the start web socket method calls to:
private void startWebSocket()
{
MonitorHub hub = new MonitorHub();
Timer myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler(hub.DisplayTimeEvent);
myTimer.Interval = 3000;
myTimer.Start();
}
that calls to a method in my hub:
public class MonitorHub : Hub
{
public void DisplayTimeEvent(object source, ElapsedEventArgs e)
{
var response = MonitorUtils.GetCorpData();
Clients.All.broadcastMessage(response);
}
}
(All is in the same project, compiled with no errs).
My client code is located in the client angular project (also under VS),
I added the required functionality within the controller:
function initWebSocket() {
self.chatHub = null; // holds the reference to hub
self.chatHub = $.connection.MonitorHub; // **I dont have MonitorHub**
$.connection.hub.start();
self.chatHub.client.broadcastMessage = function (response) {
//bla bla
};
}
I want to mention that I included in the index.html the files:
<script src="scripts/Vendor/jquery/jquery-2.2.1.js"></script>
<script src="scripts/Vendor/jquery/jquery.signalR-2.2.1.js"></script>
<script src="scripts/signalr/hubs"></script>
<script src="assets/global/plugins/angularjs/angular.min.js" type="text/javascript"></script>
$.connection.MonitorHub gets nothing - undefined.
I really believe that it has something to do with the fact that the server side
is in a different project than the client side. When I run a simple example like the chat example, it works - all in the same project.
I get in the console this error:
Error: SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. .
Any idea?
I am not 100% sure but it might be a case of JQuery version mismatch. Try using a lower jquery version e.g. jquery-1.6.4.js
You did not seem to have added SignalR server to your project. You seem to be starting a WebSocket and create an instance of a hub and throwing some Web API. This is not how SignalR works. You need to install SignalR server packages to your server and then SignalR will take care of handling your calls, instantiating your hubs etc. Just follow the tutorial you posted a link to (Setting up the project section) or this one.

connected users' list in sails socket

i've currently started using sailsJS with angularJs at frontend alognwith socket for realtime communiction.
Sailsjs gives built-in support to websocket through "sails.io.js".On client side after adding this library this code is added to angular's chat controller.
Client side code
io.socket.get('/chat',{token:token},function(users){
console.log(users);
});
chatController's action on sails side is like this.
Server side code
chat: function (req, res) {
console.log(req.isSocket);
//this gives true when called through client.
})
infact very new to sails so i want suggestion that how to maintain connected user's list because m not using redis as storage purpose.adapter is memory.array is not a good idea because it'll vanish when restart a server.m using sails version of 0.11.0.
thanx in advance.
I'm somewhat new but learning fast, these suggestions should get you there unless someone else responds with greatness...
They changed it in 11 but in 10.5 I use sockets.js in config folder and on connect I store the session data in an array with their socket.
I created a service in APIs/service that contains the array and socket associate function.
For v11 you can't do that exactly the same, but you can make your first 'hello' from the client call a function in a controller that calls the associate function.
A couple tips would be don't let the client just tell you who they are, as in don't just take the username from the params but get it from req.session
(This assumes you have user auth setup)
In my case I have
in api/services/Z.js (putting the file here makes it's functions globally accessible)
var socketList = [];
module.exports = {
associateSocket: function(session, socket) { // send in your username(string) socket(object) id(mongoId) and this will push to the socketlist for lookups
sails.log.debug("associate socket called!",socketList.length)
var iHateYou = socketList
//DEBUG
var sList = socketList
var util = require('util')
if (session.authenticated){
var username = session.user.auth.username
var userId = session.user.id
// sails.log.debug("Z: associating new user!",username,userId,socket)
if (username && socket && userId) {
sList[sList.length]= {
username: session.user.auth.username,
socket: socket,
userId: session.user.id,
};
sails.log.debug('push run!!! currentsocketList length',socketList.length)
} else sails.log("Z.associateSocket called with invalid data", username, userId, authId, socket)
}else{sails.log.warn("Z.associateSocket: a socket attempted to associate itself without being logged in")}
},
}
in my config/sockets.js
onConnect: function(session, socket) {
Z.associateSocket(session,socket)
if (session.user && session.user.auth){
sails.log("config/sockets.js: "+session.user.auth.username+" CONNECT! session:",session)
}else sails.log.warn('connect called on socket without an auth, the client thinks it already has a session, so we need to fix this')
// By default, do nothing.
},
Then you can make add some functions to your services file to do lookups based on username and passwords, remove sockets that are disconnecting and the like (I'm using waterlock for my auth at the moment, although debating the switch back to sails-generate-auth)
Remove your onConnect and dicconnect function from config/sockets.js.

why does socket.io error 500 with express.io?

Why does socket.io now give 500 (Internal Server Error) with express.io??
client side:
$(document).ready(function(){
$.getScript("http://www.mysite.com:8000/socket.io/socket.io.js",function(){
var socket = io.connect('http://www.mysite.com:8000'); //<<--error
socket.emit('ready');
});});
server side:
var express = require('express.io')
, engine = express().http().io();
engine.use(express.cookieParser());
engine.use(express.session({secret:'monkey'}));
engine.all('/',function(req,res,next){res.header("Access-Control-Allow-Origin","*");res.header("Access-Control-Allow-Headers","X-Requested-With");next();});
engine.get('/', function(req, res) {
req.session.loginDate = new Date().toString()
res.sendfile(__dirname)
});
engine.listen(8000);
engine.io.route('ready',function(socket){console.log('hellooooooooooo');});
I am following the docs on https://github.com/techpines/express.io, I have only changed two things: cross domain and app is called engine instead. I just can't see the problem Has anyone else got this to work?
Note: it's not using express.js it's using express.io (more compatable with socket.io)
It's like socket.io is not their listening on the server even though engine = express().http().io(); io is socket.io
I faced a similar problem, but I fixed it by copying and pasting the code sample in express.io sample code, and it worked. Then I compared them to check what the problem could be and observed that order of the code matters.
This order results in an error:
static
cookieParser
session
But when I followed the code provided in the sample code, I found out that this order works:
cookieParser
session
static
Hopefully this will also help you.
I believe the posted example is failing because you're using the call res.sendfile(__dirname) without supplying a filename.
This is coming from express.io, notice it uses res.sendfile(__dirname + '/client.html'):
express = require('express.io')
app = express().http().io()
// Setup your sessions, just like normal.
app.use(express.cookieParser())
app.use(express.session({secret: 'monkey'}))
// Session is automatically setup on initial request.
app.get('/', function(req, res) {
req.session.loginDate = new Date().toString()
res.sendfile(__dirname + '/client.html')
})

Resources