socket.io-client on server to connect to another server - javascript

So I have been working on setting up redundant servers without a single point of failure. I have been looking through a lot of methods and I have settled on using socket.io-client on each server to handle passing messages back and forth between the 2 servers for redundant data. However, no matter what I do, I cannot get the server to connect to the other server. I even scrapped my entire project, started a new one, using extremely simplistic code, and still cannot get the 2 to talk to each other. I have seen multiple questions like this on SO, but none of them have resolved my issue, so I decided to ask and give code samples of my ridiculously simple setup and see if anyone can see why it doesn't connect. I'm telling you, if I didn't already shave my head, I would be ripping my hair out by now. So, here is my simplistic code that doesn't work....
SERVER 1
"use strict";
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const ioClient = require('socket.io-client');
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
var client = ioClient('10.0.0.234:3000');
client.on('connect', () => {
console.log('connected to server');
});
io.on('connection', (socket) => {
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(3000, () => {
console.log('listening on *:3000');
});
SERVER 2 -- exactly the same except for the line...
var client = ioClient('10.211.55.7:3000');
To point it at the other server. These are both on my local network, and both of them are running at the same time. I even put a client page on each server with a simple connection string, one to the server on that same machine, and one to the server on the other machine, like so...
CLIENT 1 (the 10.0.0.234 machine):
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io("10.0.0.234:3000");
socket.on('connect', function() {
console.log('connected to main server');
})
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
</script>
CLIENT 2 (the 10.211.55.7 machine) - exactly the same except for the connection line which is...
var socket = io('10.211.55.7:3000');
Both of the clients work, and can connect to their servers. I even switched the IP addresses on the clients so that machine 10.0.0.234's client was using...
var socket = io('10.211.55.7:3000');
and it connected perfectly. So each client can connect to either server, and it works perfectly, but no matter what I do, I cannot get the server to ever log the 'connected to server' part.
Seriously, am I losing my mind here? IS there some random bug in socket.io-client that won't allow a server to connect to another server, even if it is running the socket.io as a client? I am so very...very... confused, annoyed, fed up, beat up... and all the other adjectives you can think of.
Just in case anyone needs it, here is my package.json file that I am running on both servers...
PACKAGE.JSON...
{
"name": "simple-socket",
"version": "0.0.1",
"description": "socket server to socket server test",
"dependencies": {
"express": "4.10.2",
"socket.io": "1.2.0",
"socket.io-client": "^1.4.5"
}
}
I know there are other ways of handling redundant backups within node.js,the actual server is much more complex running sticky-session, cluster, redis, socket.io-redis, and others. I just created a simplistic example (actually just kind of used the socket.io chat example as a base) to try to get both servers to talk to each other. No matter what though, it never actually connects to the other server. Yet, somehow both clients can connect to either server, it is just the server will not connect to the other server. Thank you for all the help, and I apologize for the novel here, I am just trying to give all the information I possibly can. Nothing more annoying than trying to help someone who won't give you anything in terms of information, and won't even do some basic research.
Here is a console.log(client); right after the "var client = ioClient('10.0.0.234:3000');
Socket {
io:
Manager {
nsps: { '/': [Circular] },
subs: [ [Object], [Object], [Object] ],
opts:
{ path: '/socket.io',
hostname: '10.0.0.234',
secure: false,
port: '3333' },
_reconnection: true,
_reconnectionAttempts: Infinity,
_reconnectionDelay: 1000,
_reconnectionDelayMax: 5000,
_randomizationFactor: 0.5,
backoff: Backoff { ms: 1000, max: 5000, factor: 2, jitter: 0.5, attempts: 0 },
_timeout: 20000,
readyState: 'opening',
uri: 'http://10.0.0.234:3333',
connecting: [ [Circular] ],
lastPing: null,
encoding: false,
packetBuffer: [],
encoder: Encoder {},
decoder: Decoder { reconstructor: null },
autoConnect: true,
engine:
Socket {
secure: false,
agent: false,
hostname: '10.0.0.234',
port: '3333',
query: {},
upgrade: true,
path: '/socket.io/',
forceJSONP: false,
jsonp: true,
forceBase64: false,
enablesXDR: false,
timestampParam: 't',
timestampRequests: undefined,
transports: [Object],
readyState: 'opening',
writeBuffer: [],
policyPort: 843,
rememberUpgrade: false,
binaryType: null,
onlyBinaryUpgrades: undefined,
perMessageDeflate: [Object],
pfx: null,
key: null,
passphrase: null,
cert: null,
ca: null,
ciphers: null,
rejectUnauthorized: null,
transport: [Object],
_callbacks: [Object] },
skipReconnect: false,
_callbacks: { '$open': [Object], '$packet': [Object], '$close': [Object] } },
nsp: '/',
json: [Circular],
ids: 0,
acks: {},
receiveBuffer: [],
sendBuffer: [],
connected: false,
disconnected: true,
subs:
[ { destroy: [Function] },
{ destroy: [Function] },
{ destroy: [Function] } ],
_callbacks:
{ '$connecting': [ [Function: onConnecting] ],
'$connect': [ [Function] ] } }

Related

Trying connection mqtt in browser

I'm trying to get a mqtt connection on my browser with JS
I'm following this tutorial: https://emqx.medium.com/use-websocket-to-connect-to-mqtt-broker-9e7baf1aa773
So I've got this:
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script>
<script>
// Globally initializes an mqtt variable
const clientId = 'mqttjs_' + Math.random().toString(16).substr(2, 8)
const host = 'ws://broker.***.***.com:9883'
const options = {
keepalive: 60,
clientId: clientId,
username: '***',
password: '***',
protocolId: 'MQTT',
protocolVersion: 4,
clean: true,
reconnectPeriod: 1000,
connectTimeout: 30 * 1000,
will: {
topic: 'WillMsg',
payload: 'Connection Closed abnormally..!',
qos: 0,
retain: false
},
}
console.log('Connecting mqtt client')
const client = mqtt.connect(host, options)
client.on('connect', () => {
console.log('Client connected:' + clientId)
// Subscribe
})
</script>
And in my browser I've got this error:
After some research, some people say that need to use certificate: https://github.com/eclipse/paho.mqtt.javascript/issues/187
So, I've got this :
<script src="../browserMqtt.js"></script>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script>
var options = {
keyPath: '../credentials/client-key.pem',
certPath: '../credentials/client-cert.pem',
rejectUnauthorized : false,
ca: ['../credentials/a-cert.pem'],
protocolId: 'MQTT',
username: '***',
password: '***',
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8)
};
var client = mqtt.connect('ws://broker.***.***.com:9883',options);
client.on('connect', function(){
console.log('Connected');
});
</script>
I've got the same error in browser ...
The broker conguration for mosquitto, it's like this :
allow_anonymous false
password_file /mosquitto/config/passwd
#TCP
listener 1883
socket_domain ipv4
#SSL
listener 8883
socket_domain ipv4
cafile /mosquitto/config/tls/ca/ca-cert.pem
certfile /mosquitto/config/tls/server/server-cert.pem
keyfile /mosquitto/config/tls/server/server-key.pem
tls_version tlsv1.2
socket_domain ipv4
#WSS
listener 9883
socket_domain ipv4
protocol websockets
cafile /mosquitto/config/tls/ca/ca-cert.pem
certfile /mosquitto/config/tls/server/server-cert.pem
keyfile /mosquitto/config/tls/server/server-key.pem
tls_version tlsv1.2
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
log_timestamp_format %Y-%m-%dT%H:%M:%S
log_type all
I can't understand how can I solve it ? Thanks for your help
You can't use client side certs in the browser to authenticate the client (unless you load them into the browsers keystore, but even then I'm not convinced it will work unless there is only one cert/key for the browser to pick as javascript code won't normally prompt the user to pick the right one).
Also loading client certs over http from the server totally defeats the point of using a client cert as anybody can download them.
You need to remove all of the following from the options
keyPath: '../credentials/client-key.pem',
certPath: '../credentials/client-cert.pem',
rejectUnauthorized : false,
ca: ['../credentials/a-cert.pem'],
protocolId: 'MQTT',
Because the paths are meaningless in the browser (and for the reasons I mentioned earlier)
You should also be starting your broker URL with wss:// to make it clear you are trying to connect over secure WebSockets.

How to reconnect Pubnub after internet reconnect in javascript?

I have a Pubnub instance,
I want to know how to handle reconnection when internet does down and comes back up with like a given number of retries? The documentation definitely gives the appropriate docs but I am unable to put it into code.
Help would be greatly appreciated.
my code:
this.pubnub = new PubNub({
subscribeKey: this.serverDetails.authInfo.subscribeKey,
authKey: this.serverDetails.authInfo.authKey,
uuid,
restore: true,
ssl: true
});
this.listeners = {
message: msgEvent => {
console.log(msgEvent);
},
status: statusEvent => {
}
};
this.pubnub.addListener(this.listeners);
Set restore:true in your init code.
this.pubnub = new PubNub({
subscribeKey: this.serverDetails.authInfo.subscribeKey,
authKey: this.serverDetails.authInfo.authKey,
uuid,
ssl: true,
restore: true // this allows reconnect to restore your channel subscription
});

Unable to run the multichain-node (npm module) in client side(browser)

let multichain = require("multichain-node")({
port: 6001,
host:'localhost',
user:'myuser',
pass:'mypassword'
});
multichain.getInfo((error,info) => {
if(error){
throw error;
}
console.log(info);
})
output:version: '1.0',
nodeversion: 10000901,
protocolversion: 10008,
chainname: 'chain1',
description: 'chain1',
protocol: 'multichain',
port: 6001,
setupblocks: 60,
nodeaddress: 'mulmul#localhost:6001',
burnaddress: '1XXXXXXWh4XXXXXXXyXXXXXXZdXXXXXXYjGhfn',
incomingpaused: false,
miningpaused: false,
walletversion: 60000,
balance: 0,
walletdbversion: 2,
reindex: false,
blocks: 127,
timeoffset: 0,
connections: 0,
proxy: '',
difficulty: 6e-8,
testnet: false,
keypoololdest: 1506490805,
keypoolsize: 2,
paytxfee: 0,
relayfee: 0,
errors: '' }
this output displayed in command prompt, How can i execute this code in browser
multichain-node is a node module; it doesn't make sense to run it in the browser.
In particular it uses node's http module to make http requests; if you wanted to do that in the browser you'd need to use fetch or XMLHttpRequest to do that, and you would need CORS to be set up correctly.

Websocket SSL connection

I am trying to test a secure websocket but I'm having trouble. Here is my test:
var WebSocket = require('ws');
describe('testing Web Socket', function() {
it('should do stuff', function(done) {
var ws = new WebSocket('wss://localhost:15449/', {
protocolVersion: 8,
origin: 'https://localhost:15449'
});
ws.on('open', function() {
console.log('open!!!');
done();
});
console.log(ws);
});
});
Here's the log of "ws" after it's created:
{ domain: null,
_events: { open: [Function] },
_maxListeners: undefined,
_socket: null,
_ultron: null,
_closeReceived: false,
bytesReceived: 0,
readyState: 0,
supports: { binary: true },
extensions: {},
_isServer: false,
url: 'wss://localhost:15449/',
protocolVersion: 8 }
I don't get a log back from open. I am running the project locally and when I use the Chrome Advanced Rest Client tool I am able to connect just fine.
Am I missing something? Please help.
Edit:
I added ws.on('error') and it logged out { [Error: self signed certificate] code: 'DEPTH_ZERO_SELF_SIGNED_CERT' }
I've also tried following this code but get the same error.
The https module is rejecting your self-signed cert (as one would hope). You can force it to stop checking by passing a rejectUnauthorized: false option (which WebSocket will pass down to https):
var ws = new WebSocket('wss://localhost:15449/', {
protocolVersion: 8,
origin: 'https://localhost:15449',
rejectUnauthorized: false
});

Catch webhook node.js

I'm trying to catch a PUT/webhook request that is being made by the Aftership API in node.js. A PUT request is made each time a push notification is needed to be made, I am using Parse to send the notifications but I need some of the data from the webhook.
The header of the webhook looks like Content-Type: application/json And contains this data:
ts - UTC unix timestamp that the event occurred
event - the name of the event (for tracking update, the value will be
'tracking_update')
msg - details about the message for which the event occurred, in the
following format.
How would I go about getting the tracking number, slug and the value for token in the custom fields dictionary in node or js?
{
"event": "tracking_update",
"msg": {
"id": "53aa94fc55ece21582000004",
"tracking_number": "906587618687",
"title": "906587618687",
"origin_country_iso3": null,
"destination_country_iso3": null,
"shipment_package_count": 0,
"active": false,
"order_id": null,
"order_id_path": null,
"customer_name": null,
"source": "web",
"emails": [],
"custom_fields": {},
"tag": "Delivered",
"tracked_count": 1,
"expected_delivery": null,
"signed_by": "D Johnson",
"shipment_type": null,
"tracking_account_number": null,
"tracking_postal_code": "DA15BU",
"tracking_ship_date": null,
"created_at": "2014-06-25T09:23:08+00:00",
"updated_at": "2014-06-25T09:23:08+00:00",
"slug": "dx",
"unique_token": "xk7LesjIgg",
"checkpoints": [{
"country_name": null,
"country_iso3": null,
"state": null,
"city": null,
"zip": null,
"message": "Signed For by: D Johnson",
"coordinates": [],
"tag": "Delivered",
"created_at": "2014-06-25T09:23:11+00:00",
"checkpoint_time": "2014-05-02T16:24:38",
"slug": "dx"
}]
},
"ts": 1403688191
}
It can be done with Express framework, example:
var express = require('express'),
bodyParser = require('body-parser'),
app = express(),
port = 3000;
app.use(bodyParser.json());
app.post('/', function (req, res) {
var body = req.body;
var trackingNumber = body.msg.tracking_number;
var slug = body.msg.slug;
var token = body.msg.unique_token;
console.log(trackingNumber, slug, token);
res.json({
message: 'ok got it!'
});
});
var server = app.listen(port, function () {
var host = server.address().address
var port = server.address().port
console.log('Example app listening at http://%s:%s', host, port)
});
Here is the GIT repository, just clone it and do npm install and then npm start. The server will run on port 3000 :D
Note: I saw in Aftership Webhook's documentation, it said they will request POST HTTP method, not PUT so I create an example of post request. Just replace it with put if you want it to catch put request.
For inspecting webhooks data, I would suggest to store every request in database and then query database. As each request is different, easiest way would be creating API in sails.js (Node.js framework with easy to use ORM).
sudo npm install sails -g
sails new _project_name_
cd _project_name_
sails generate api Records
With last command, sails has generated controller and model to store your webhook data.
I suggest installing pm2 for running app. you can run it with
pm2 start app.js
Next you should configure your webhook in Aftership for following url:
YOUR_SERVER_IP:PORT/Records/create
you can inspect data by following url:
YOUR_SERVER_IP:PORT/Records/find
if you want to parse data, it can be done in RecordsController.js, for example:
Parsing: function(req, res) {
Records.find({}).exec(function(err, results) {
var output = [];
while (results.length) {
var result = results.pop();
//custom parsing goes here
//example:
output.push({
tracking_number: result.msg.tracking_number,
slug: result.msg.slug,
unique_token: result.msg.unique_token
});
}
return res.json(output);
});
},
You can call this method via following url:
YOUR_SERVER_IP:PORT/Records/Parsing
I have created project in Codeanywhere for demonstration
webhook endpoint is:
http://port-1337.zavtt4t8a0jm7vigncyo3txxmuhxgvix3yxk66pvydgqfr.box.codeanywhere.com/records/create
For inspecting data, just replace /create part of url to /find
git repo is here: https://github.com/dkatavic/webhook_for_aftership
you can just clone the project on your server and run it (or use my server for testing)
You can catch PUT request by
app.put('/someRouteToCatchWebHook', function(request, response) {
//webhook parsing goes here
});
(i'm sure that you use expressjs in your code - see http://expressjs.com/api.html#app.METHOD for details).
If the webhook data is in request body, you can use the https://www.npmjs.com/package/body-parser module for parsing it.

Categories