Socket.io client not working properly - ruby-on-rails

I have created chat application using following
Rails
Rabbitmq
nodejs ( with amqplib/callback_api and socket.io )
I have following code in server side
var amqp = require('amqplib/callback_api');
var amqpConn = null;
var app = require('http').createServer()
var io = require('socket.io')(app);
var fs = require('fs');
io.on('connection', function (socket) {
socket.emit('news/1', msg.content.toString());
// socket.disconnect()
});
client side
<%= javascript_include_tag "http://localhost:53597/socket.io/socket.io.js" %>
<script>
var socket = io('http://localhost:53597', {reconnect: true});
socket.on('connect', function () {
console.log('connected');
socket.on('news/1', function (msg) {
console.log('inside coming');
console.log(msg);
});
});
</script>
When I send message, message successfully pushed to queue and messages emitted to socket. The problem is I can get messages when only refresh page and messages are not deleted.
I can't understand what was wrong here ?

Eventually I fixed my issue, the problem is I have placed emit function inside connection event, so that I can get data when only connection established​, connection is established when page load that is the reason I get data when only page load.
I have the following code for emit data
io.sockets.emit('news/1', msg.content.toString());

Related

Unable to establish connection between Node.JS and React-Native (Socket.IO)

I'm new to React and Node and i'm trying to make a simple WebSocket using Socket.IO which gonna simply send greetings to all connected users and the user will respond to the server.
The Node.JS server is running on a Windows PC while the React-Native app is running on both iOS and Android devices.
Node.JS server code is the following
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
const bodyParser = require('body-parser');
const mysql = require('mysql');
const connection = mysql.createPool({
host : 'localhost',
user : 'root',
password : 'block',
database : 'visualpos'
});
// Creating a GET route that returns data from the 'users' table.
app.get('/prenotazioni', function (req, res) {
// Connecting to the database.
connection.getConnection(function (err, connection) {
// Executing the MySQL query (select all data from the 'users' table).
connection.query("SELECT Data, Importo_Doc FROM tabella_pagamenti", function (error, results, fields) {
// If some error occurs, we throw an error.
if (error) throw error;
// Getting the 'response' from the database and sending it to our route. This is were the data is.
res.send(results)
});
connection.release();
});
});
app.get('/', function(req, res){
res.send('<h1>Hello World</h1>');
});
// Starting our server.
http.listen(3000, () => {
console.log('In ascolto sulla porta *:3000');
});
io.emit('saluta', 'Ciao dal server :)');
io.on('connected', (data) => {
console.log(data);
});
Actually GET part of the code works perfectly but the Socket.IO seems death.
The client doesn't get any response and server the same i think the Socket.IO server simply doesn't start..
In XCode Debug i get the following errors when the app is running on the iPhone
And i even get on both devices warning "Unrecognized WebSocket connection option(s) 'agent', 'perMessageDeflate',..."
And here is the code i'm using in React-Native
import io from 'socket.io-client'
var socket = io('http://192.168.100.50:3000', {
jsonp: false,
transports: ['websocket'],
autoConnect: true,
reconnection: true,
reconnectionDelay: 500,
reconnectionAttempts: Infinity
});
componentDidMount(){
socket.emit('connected','we');
socket.on('saluta',(data) => { alert(data); });
}
On socket.io getStarted section, they use a "connection" event instead of "connected" (https://socket.io/get-started/chat/).
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
});

socket.io can't handle errors

I'm trying to make real time application with node.js and socket.io. As I can see the server can see when new user connects but can't return information to client side or something. This is what I've on client side:
<script src="<?= base_url('assets/js/socket.io.js') ?>"></script>
<script>
var socket;
socket = io('http://***.***.***.***:3030', {query: "key=key"});
socket.on('connect', function (data) {
console.log('Client side successfully connected with APP.');
});
socket.on('error', function (err) {
console.log('Error: ' + err);
});
</script>
and this is the server side:
var app = require("express")();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
http.listen(3030, function () {
globals.debug('Server is running on port: 3030', 'success');
});
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('www.****.com' == domain) {
globals.debug('New user connected', 'warning');
} else {
globals.debug('Bad site authentication data, chat will be disabled.', 'danger');
return accept('Bad site authentication data, chat will be disabled.', false);
}
});
io.use(function (sock, next) {
var handshakeData = sock.request;
var userToken = handshakeData._query.key;
console.log('The user ' + sock.id + ' has connected');
next(null, true);
});
and when someone comes to website I'm expecting to see in console output "New user connected" and I see it: screen shot and the user should see on the browser console output: "Client side successfully connected with APP." but I doesn't show. Also I tried to emit data to user but it doesn't work too. I can't see any errors or something. This is not the first time I'm working with sockets but the first time facing such as problem. Maybe there is any error reporting methods to handle errors or something? Also I can't see output on io.use(....) method
The solution is to pass "OK" sign just after authenticating to do the next method:
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('www.****.com' == domain) {
globals.debug('New user connected', 'warning');
accept(null, true);
} else {
globals.debug('Bad site authentication data, chat will be disabled.', 'danger');
return accept('Bad site authentication data, chat will be disabled.', false);
}
});

Using RabbitMQ with Ruby and Node.js apps?

I'm using the Bunny gem in Rails and AMQP in Node.js.
Rails is the publisher and the Node.js app is a subscriber.
Code from Rails:
conn = Bunny.new
conn.start
ch = conn.create_channel
x = Bunny::Exchange.new(ch, :direct, "messenger")
q1 = ch.queue("new_messages").bind(x, :routing_key => 'send')
x.publish('hi', :routing_key => 'send')
Code from Node.js:
var amqp = require('amqp');
var connection = amqp.createConnection();
connection.addListener('ready', function(){
var exchange = connection.exchange('messenger');
var queue = connection.queue('new_messages')
queue.bind('messenger', 'send')
queue.subscribe( {ack:true}, function(message){
console.log(message.data.toString())
queue.shift()
});
});
From the management plugin I can see that the Rails code works well, but the code from Node.js doesn't make sense.
Where is my mistake?
The main issue is in how you're attempting to bind your queue to the 'messenger' exchange. You've already used the exchange name to get a reference to the exchange object. Rather than pass in the string name again when binding the queue to the exchange, pass this reference into queue.bind(). Simply change the first queue.bind() argument:
var exchange = connection.exchange('messenger');
var queue = connection.queue('new_messages');
// Use the reference to the exchange object you just received;
// pass it in here instead of the exchange's name
queue.bind(exchange, 'send');
EDIT
Here is a full, working example; just drop in your own connection properties:
var amqp = require('amqp');
var connection = amqp.createConnection({
host: 'my_host',
login: 'my_login',
password: 'my_password',
authMechanism: 'AMQPLAIN',
vhost: 'my_vhost'
});
connection.addListener('ready', function(){
console.log('ready');
var exchange = connection.exchange('messenger');
var queue = connection.queue('new_messages');
queue.bind(exchange, 'send');
// if message successfully received, print message
queue.subscribe( {ack:true}, function(message){
console.log(message.data.toString());
queue.shift();
});
// test by sending a message
exchange.publish('send', 'this is a test message', {}, function() {})
});
Cheers.

how to parse a request in a node.js server built on net module

We are building a server with net module, and having hard time extracting the URL (and resource path) from the request. The following code crashes, saying:
Parameter 'url' must be a string not undefined.
File netServer.js:
var net = require('net');
var url = require('url');
var server = net.createServer(function(socket) { //'connection' listener
socket.on('connect', function(request) {
});
socket.on('data', function(request) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
});
socket.on('end', function() {
});
});
server.listen(8080, function() { //'listening' listener
console.log('server bound');
});
Any suggestions?
Are you trying to build an HTTP server? net is a TCP package, so all you get is the remoteAddress and remotePort, the rest will be sent on the data handler (which is just passed a Buffer, or a string, depending on the encoding).
Use the HTTP module for this, because it does all of the parsing for you.

two way communication between extension and content javascript files

i am trying to accomplish a two way communication request response in my firefox sidebar extension, i have a file named event.js this resides on the content side, i have another file called sidebar.js file which is residing in the xul. I am able to communicate from event.js to sidebar.js file using the dispatchEvent method. my event in turn raises a XMLHttpRequest in sidebar.js file which hits the server and sends back the response. Now, here i am unable to pass the response to the event.js file. I want the response to be accessed in the event.js file. Till now i have achieved only one way communication. Please help me in getting the two way communication.
Code is as follows:
// event.js file
// This event occurs on blur of the text box where i need to save the text into the server
function saveEvent() {
var element = document.getElementById("fetchData");
element.setAttribute("urlPath", "http://localhost:8080/event?Id=12");
element.setAttribute("jsonObj", convertToList);
element.setAttribute("methodType", "POST");
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent("saveEvent", true, true);
element.dispatchEvent(evt);
//Fetching the response over here by adding the listener
document.addEventListener("dispatchedResponse", function (e) { MyExtension.responseListener(e); }, false, true);
}
var MyExtension = {
responseListener: function (evt) {
receivedResponse(evt.target.getAttribute("responseObject"));
}
}
function receivedResponse(event) {
alert('response: ' + event);
}
// sidebar.js file
window.addEventListener("load", function (event) {
var saveAjaxRequest = function (urlPath, jsonObj, methodType, evtTarget) {
var url = urlPath;
var request = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onload = function (aEvent) {
window.alert("Response Text: " + aEvent.target.responseText);
saveResponse = aEvent.target.responseText;
//here i am again trying to dispatch the response i got from the server back to the origin, but unable to pass it...
evtTarget.setAttribute("responseObject", saveResponse);
document.documentElement.appendChild(evtTarget);
var evt = document.createEvent("dispatchedRes"); // Error line "Operation is not supported" code: "9"
evt.initEvent("dispatchedResponse", true, false);
evtTarget.dispatchEvent(evt);
};
request.onerror = function (aEvent) {
window.alert("Error Status: " + aEvent.target.status);
};
//window.alert(methodType + " " + url);
request.open(methodType, url, true);
request.send(jsonObj);
};
this.onLoad = function () {
document.addEventListener("saveEvent", function (e) { MyExtension.saveListener(e); }, false, true);
}
var MyExtension =
{
saveListener: function (evt) {
saveAjaxRequest(evt.target.getAttribute("urlPath"), evt.target.getAttribute("jsonObj"), evt.target.getAttribute("methodType"), evt.originalTarget);
}
};
});
Why are you moving your fetchData element into the sidebar document? You should leave it where it is, otherwise your content code won't be able to receive the event. Also, use the content document to create the event. Finally, document.createEvent() parameter for custom events should be "Events". So the code after your //here i am again trying comment should look like:
evtTarget.setAttribute("responseObject", saveResponse);
var evt = evtTarget.ownerDocument.createEvent("Events");
evt.initEvent("dispatchedResponse", true, false);
evtTarget.dispatchEvent(evt);
Please note however that your code as you show it here is a huge security vulnerability - it allows any website to make any HTTP requests and get the result back, so it essentially disables same-origin policy. At the very least you need to check that the website talking to you is allowed to do it (e.g. it belongs to your server). But even then it stays a security risk because server response could be altered (e.g. by an attacker on a public WLAN) or your server could be hacked - and you would be giving an attacker access to sensitive data (for example he could trigger a request to mail.google.com and if the victim happens to be logged in he will be able to read all email data). So please make this less generic, only allow requests to some websites.

Resources