How to use Websocket (socket.io) with Ruby? - ruby-on-rails

I need to implement WebSocket synchronization in our Rail project. MetaApi project's use Socket.Io as default support. Only found 2 projects (websocket-client-simple) and outdated with native socket.io. We try to implement this with Faye-Websocket and socketcluster-client-ruby but without success.
Code Example
import ioClient from 'socket.io-client';
const socket = ioClient('https://mt-client-api-v1.agiliumtrade.agiliumtrade.ai', {
path: '/ws',
reconnection: false,
query: {
'auth-token': 'token'
}
});
const request = {
accountId: '865d3a4d-3803-486d-bdf3-a85679d9fad2',
type: 'subscribe',
requestId: '57bfbc9f-108d-4131-a300-5f7d9e69c11b'
};
socket.on('connect', () => {
socket.emit('request', request);
});
socket.on('synchronization', data => {
console.log(data);
if (data.type === 'authenticated') {
console.log('authenticated event received, you can send synchronize now');
}
});
socket.on('processingError', err => {
console.error(err);
});

Socket.io protocol is a bit more complicated than a simple websocket connection, with the latter being only one of the used transports, see description in official repository. Websockets are used only after initial http handshake, so you need a somewhat full client.
I'd start with trying to consume events with a js client stub from browser, just to be sure the api is working as you expect and determine used and compatible socket.io versions (current is v4, stale ruby clients are mostly for v1). And you can peek into protocol in browser developer tools.
Once you have a successful session example and have read protocol spec above - it will be easier to craft a minimal client.

Related

MQTT on Parse platform (Open source parse Server)

Hi I am using the hosted version of the open source parse platform (hosed version on Back4app) for my IoT project. Am using HTTP (REST) Api to communicate with the parse server and upload data. Does anyone know if it is possible to use the MQTT protocol instead of HTTP for the same with the parseplatform. I couldn't find any relevant doc for this. Apparently there's a way to install the MQTTjs on cloud code section of the platform but do not know if this really works ... Thanks in advance
Yes, it's possible, I just tested it now and it worked for me. Here are the steps that you need to follow:
1 - You only need to install this npm module as you can see at this guide.
Here is my package.json:
{
"dependencies": {
"mqtt": "2.18.8"
}
}
2 - After that, on Back4app, you need to upload the code in your cloud code and check your Server System Logs at Server Settings > Logs > Settings.
Here's a simple code that you can use to test it. I put this code in my main.js:
var mqtt = require('mqtt')
var client = mqtt.connect('mqtt://test.mosquitto.org')
client.on('connect', function () {
client.subscribe('presence', function (err) {
if (!err) {
client.publish('presence', 'Hello mqtt')
}
})
})
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString())
client.end()
});

React Native Network request Failed on fetch - Works Local

I am using some code in a React Native component that is a simple fetch passing a parameter to OMDB API. This could be a CORS issue since if I run it in the format below going directly to omdbapi.com it fails always with Network request Failed. This request however works in the Android emulator on the same network.
// The fetchData function makes an AJAX call to the OMDB API.
fetchData(movieinput) {
console.log("In fetch");
// We pass the movie the user entered in into the URL for the API call.
fetch('http://www.omdbapi.com/?t='+movieinput+'&y=&plot=short&r=json')
.then((response) => response.json())
.then((responseData) => {
// After the data is recieved, we set this.state.movie to the result of the API call.
this.setState({
movie: responseData,
});
})
.done();
}
If however I run the same code going to a local URL that wraps the remote request into a localhost request, it works correctly.
fetchData(movieinput) {
console.log("In fetch");
// We pass the movie the user entered in into the URL for the API call.
fetch('http://localhost:3000/movie/'+movieinput)
.then((response) => response.json())
.then((responseData) => {
// After the data is recieved, we set this.state.movie to the result of the API call.
this.setState({
movie: JSON.parse(responseData),
});
})
.done();
}
Any ideas?
The problem is probably App Transport Security, an iOS specific restriction that (by default) forces apps to use https for all network communication. Here is a video tutorial explaining how to tweak ATS so that your react native app will work: http://codecookbook.co/post/how-to-make-network-requests-in-react-native/

YUI3 and socket.io

Just a simple question:
I am using YUI3 framework for my website and want to use socket.io framework.
Now challenge is to use socket.io with YUI3.
As of now I am using socket.io logic inside YUI sandbox and its working fine.
BUT can there be any fallback of this approach ? If yes, then how should I integerate both ?
Here is the snippet of code:
<script type="text/javascript">
YUI().use('my-slide' , 'node', 'event','transition', function (Y) {
// connecting to nodejs server running on 7001 port for dynamic updates
var broadcast = io.connect('http://localhost:7001/getlatestbroadcast');
broadcast.on('status',function(data){
// some socket logic here
});
// Setting Listener
broadcast.on('moreData',function(data){
// some socket logic here
});
});
</script>
What you're doing definitely works, and there's no problem in using it that way unless you have a conflict with some other variable named io. A slightly more effective way of using Socket.IO (or any other external module in YUI) is to namespace it on the Y object instead:
YUI({
modules: {
'socket.io': {
fullpath: '/socket.io/socket.io.js'
}
},
onProgress: function (e) {
if (e.data[0].name === 'socket.io') {
YUI.add('socket.io', function (Y) {
Y.Socket = io;
});
}
}
}).use('socket.io', function (Y) {
var socket = Y.Socket.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
});
This takes the example from the socket.io website and lets you namespace it as Y.Socket. That way, only when you specifically do YUI().use('socket.io'), will you actually be able to access Y.Socket, which helps with keeping your code organized and loaded in the correct order, thanks to the YUI Loader.
Also, feel free to check out the Socket Model Sync YUI Gallery module I created, if you're looking for an easier way to integrate your YUI App Framework application with Socket.IO.
Hope this helps, and let me know if you have any more questions about integrating the two!

How to best serve a GridFS stored file (PDF) via my Express.js driven API to a connected client (iOS)?

I'm developing a REST HTTP API that has iOS clients connecting to it. The way it's currently set up (and tested with POSTman chrome ext) is that I make the request for the resource, and I have to wait for the whole thing to get read in and spit out for it to show up as a response.
Is this a good method for iOS and Mac client consumption or is there a better method for serving from GridFS?
I'm doing the following:
// Download a PDF
app.get('/api/download-pdf/:pdf_id', function(req, res){
var gfs = new mongodb.GridStore(mongoose.connection.db, ObjectID(req.params.pdf_id), "r");
gfs.open(function(err,gs) {
if (err){
res.send(500);
}
else{
gs.read(function(err,data) {
res.header('Content-type','application/pdf');
res.send(data);
gs.close(function(err) {});
if (err) throw(err);
});
}
});
});
the node driver now supports streaming to/from GridFS http://christiankvalheim.com/post/29753345741/new-features-in-the-driver-for-mongodb-2-2?8e43c3e0
gs.pipe(anotherStream)
See Streams

Backbone Model from Hub in SignalR

How can i create/convert this script into model in Backbone that can use SignaR Hubs? For example:
<script type="text/javascript">
$(function () {
// Proxy created on the fly
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.addMessage = function (message) {
alert("message");
};
// Start the connection
$.connection.hub.start();
});
</script>
EDIT
I did come up with this:
window.Message = Backbone.Model.extend({
hub: undefined,
initialize: function () {
this.hub = $.connection.message;
},
addMessage: function (message) {
alert(message);
},
connect: function () {
$.connection.hub.start();
var messages = this.hub.getAll();//get messages
}
});
but this is not working due to the following error:
this error: :55885 Unexpected response code: 200
If you use default settings SignalR will first try to send a websockets poll to the server. The :55885 is simply the port number of your server. Websockets protocol expects a response status code of 101 (see http://dev.w3.org/html5/websockets/).
If running IIS, unless you run Windows 8 with ASP.NET 4.5 your webserver, it will not recognize a web sockets request and (begin speculation) treat it as a normal get request and return status code 200 (OK) (end speculation) which is an unexpected response in the eyes of the websockets initiator. When this happens SignalR falls back to longpolling instead.
This might not answer your question but it will help you understand the error you get (which is likely not the reason why your code doesn't work)
Also, check out http://srtsolutions.github.com/backbone.signalr/ which is a Backbone.js/SignalR integration Nuget package.

Resources