How to communicate between Air Action Script application and Node.js server - actionscript-3

can someone please suggest way to communicate between Air(Action script) App and node.js server?
e.g.
Communication between PHP and Flash(Action Script) application using AMFPHP
BlazeDS for Java+Adobe Flex and Adobe Integrated Runtime (AIR)
Please send me your suggestions, any tutorial, or PoC sample code
Thanks in Advance.

Here is a sample I wrote for a blog. I think the code itself pretty much explains itself.
Client Side AS3 Code :
var urlString:String = "http://localhost:1337/";
function Submit():void
{
var requestVars:URLVariables = new URLVariables();
requestVars.Username = "guest";
var request:URLRequest = new URLRequest();
request.url = urlString;
request.method = URLRequestMethod.GET;
request.data = requestVars;
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, loaderCompleteHandler);
try { loader.load(request); }
catch (error:Error) { // Handle Immediate Errors }
}
function loaderCompleteHandler(e:Event):void
{
trace(e.target.data); // Response Text
}
Brief about the code snippet:
We fill in the request data by instantiating a URLVariables class as
requestVars.
We fill in the url & method by instantiating URLRequest class as request.
We attach an load complete event Handler to handle the response.
Wrapping up for catching errors, we call the load method.
URL is set to Localhost port 1337 where the nodeJS would be hosted.
The variable set is a test field UserName which is checked for in the server script.
Server Side NodeJS Code :
var http = require('http'), url = require('url');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
var urlObj = url.parse(req.url, true);
if(urlObj.query["Username"] == "guest") res.end("True");
else res.end("False");
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');
Brief about the code snippet:
The code listens at port 1337 in the localhost server where it is hosted.
The query string is unwrapped to get the UserName variable & tested.
Server Responds with true since the value equates to guest.

Related

How to send Data to the client with out client requesting the ws server in nodejs

I need to convert a csv file to json format and send it to a client requesting to ws server in nodejs ,
the file will be updated so many times so i need to send updated data to client
i am able to send data once it is loaded completely(like when app is started it sends all data in file to client) but when i update data in the file the updated data is being printed out on console but it is not being sent to client is their any thing wrong in my code
my node.js code:
var ts = require('tail-stream');
var Converter = require("csvtojson").Converter;
var converter = new Converter({constructResult:false}); //for big csv data
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
// process HTTP request. Since we're writing just WebSockets server
// we don't have to implement anything.
response.write('hello');
console.log('in http server \n');
});
server.listen(1337, function() { });
// create the server
wsServer = new WebSocketServer({
httpServer: server
});
// WebSocket server
wsServer.on('request', function(request) {
var connection = request.accept(null, request.origin);
console.log('wsserver');
connection.send('ws server');
converter.on("record_parsed", function (jsonObj) {
console.log(jsonObj); //here is your result json object
connection.send(jsonObj);
});
var tstream = ts.createReadStream('log.csv', {
beginAt: 0,
onMove: 'follow',
detectTruncate: false,
onTruncate: 'end',
endOnError: false
});
tstream.pipe(converter);
});
Right now you are creating a new read stream and adding a listener to the converter on every new connection, that will cause trouble once you have more than one client (same event emitted multiple times, etc..). Instead of that you should keep just one reader and notify all open connections when there's a new record.
Also notice that the library you are using only accepts UTF-8 strings or binary type messages, row objects sent the way you're sending them now will be received as a "[object Object]" string after toString() is called on them. You should probably send just send the row string or use JSON.stringify / JSON.parse.
Try this:
var http = require("http");
var tailStream = require("tail-stream");
var Converter = require("csvtojson").Converter;
var WebSocketServer = require("websocket").server;
var server = http.createServer();
var wsServer = new WebSocketServer({ httpServer: server });
var converter = new Converter({constructResult:false});
var logStream = tailStream.createReadStream("log.csv", { detectTruncate : false });
var connections = [];
server.listen(1337);
logStream.pipe(converter);
//----------------------------------------------------
converter.on("record_parsed", function (jsonObj) {
connections.forEach(function(connection){
connection.send(JSON.stringify(jsonObj));
});
});
//----------------------------------------------------
wsServer.on("request", function(request) {
var connection = request.accept(null, request.origin);
connection.on("close", function() {
connections.splice(connections.indexOf(connection), 1);
});
connections.push(connection);
});
The code above works, tested like this on the client side:
var socket = new WebSocket('ws://localhost:1337/');
socket.onmessage = function (event) {
console.log(JSON.parse(event.data));
}
Note: this doesn't send the whole content of the file at the beginning, just the updates, but you can easily achieve this storing the records and sending them on new connections.

Send UDP packet to local port

I'm using the following C# code to send a packet to a local port.
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9000);
byte[] send_buffer = Encoding.ASCII.GetBytes("Test message");
sock.SendTo(send_buffer, endPoint);
How can I do the same in a few calls in Actionscript? I don't need any two way communication or overhead: just as little code as possible to send a packet of text to a UDP server that I'm running in a C# app.
I've tried creating a javascript function to accept an ExternalInterface call and sending it on from Javascript with Node.js, but I think there might be an easier way of doing it.
//FLASH
ExternalInterface.call("sendToUDP", "Test message");
//HTML
<script language="JavaScript" type="text/javascript">
function sendToUDP(message)
{
//Some code to send a UDP packet from Javascript
}
</script>
Using DatagramSocket in AIR, this should be the equivalent AS3 to your C# code:
var socket:DatagramSocket = new DatagramSocket();
var address:String = "127.0.0.1", port:int = 9000;
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes("Test message");
socket.send(bytes, 0, 0, address, port);

Trying to get user timeline from twitter using application-only authentication

I'm trying to get a simple app working from within Flash to see a users tweets.
I 'believe' I have correctly gotten the access token.
var bearerToken:String;
var consumerKey:String = <CONSUMER_KEY>;
var consumerSecret:String = <CONSUMER_SECRET>;
//encode key and secret according to twitter's website
var bearerTokenCredentials = Base64.encode(consumerKey + ':' + consumerSecret);
//setup my request variables, according to twitters dev info, use client_credentials for grant_type
var requestVars:URLVariables = new URLVariables();
requestVars.grant_type = 'client_credentials';
//according to twitter, the url to use for application-only authenticaton
var url:String = 'https://api.twitter.com/oauth2/token';
//setup a URLRequest object with the proper headers, according to twitter, need the Authorization header to be 'Basic <encoded key/secret>' and the proper Content-Type header
var request:URLRequest = new URLRequest(url);
request.requestHeaders = [new URLRequestHeader('Authorization', 'Basic ' + bearerTokenCredentials),
new URLRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8')];
request.method = URLRequestMethod.POST;
request.data = requestVars;
//send the request to authenticate
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, onBearerTokenRequest);
urlLoader.load(request);
function onBearerTokenRequest(e:Event):void
{
trace('onRequestComplete');
//this works and i get a token
bearerToken = JSON.decode(e.currentTarget.data).access_token;
//HERE IS WHERE I CAN'T FIGURE OUT WHAT'S WRONG
var url:String = 'https://api.twitter.com/1.1/statuses/user_timeline.json'
var urlVariables = new URLVariables();
urlVariables.screen_name = 'rivercitygraphx';
urlVariables.count = 2;
var request:URLRequest = new URLRequest(url);
request.method = "GET";
request.requestHeaders = [new URLRequestHeader('Authorization', 'Bearer ' + bearerToken)];
request.data = urlVariables;
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, onTimelineRequestComplete);
urlLoader.load(request);
}
function onTimelineRequestComplete(e:Event):void
{
trace('onTimelineRequestComplete');
}
I get the token back properly (well I assume so since I get a long string).
But when I try to make the request for the user timeline I get an ioError Error opening URL 'https://api.twitter.com/1.1/statuses/user_timeline.json?screen%5Fname=kamcknig&count=2' which makes me think the URL is malformed, but according to everytihng I see, it seems correct.
Also, right now I'm just testing this within the Flash IDE.
Can anyone help??
I have since used the POSTMAN extension in Chrome and entered the url, and the Authorization header with the bearer token that I received and the request worked within POSTMAN!
So the only thing that i can think is it's the Flash IDE. Anyone have any ideas why that might be or if that might actually even be the problem?
OK after all my research it looks like this is impossible.
I have found a library that uses a socket connection that can do what I want, but the filesize is far too large. The Socket class in AS3 is not a secure socket so I can't use it. And the SecureSocket class can't be used either since I am limited to Flash Player 10 and earlier.
So as far as I'm concerned, this is impossible.

Send a message from client to server

I have a server I wrote in NodeJs which listens to port 1234.
From my client (html) I want to send request to my server and wait for an answer.
I tried to use XMLHttpRequest:
var http = new XMLHttpRequest();
var url = "127.0.0.1:1234";
var params = "token=22";
http.open("post", url, true);//"https://www.google.com/search?q=asd"
http.setRequestHeader("Content-type", "text/html");
http.setRequestHeader("Content-length", 0);
http.setRequestHeader("Connection", "keep-alive");
http.onreadystatechange = function() {//Call a function when the state changes.
alert(http.responseText);
}
http.ontimeout = function()
{
alert("timeout");
}
http.timeout=10;
try
{
http.send(null);
}
catch(ex)
{
alert(ex);
}
But I always got exception. The reason was I can't use my own port.
Is There any other way to send request and get respond?
There is nothing wrong with using JQuery.ajax to make your life easier and it does get a lot easier with jquery especially when it comes to XMLHttpRequest.

Sending POST variables via an AIR application

I'm trying to send data via POST, since it's far too long to send via GET.
Here's the code I'm using...
pdfUrl.method = URLRequestMethod.POST;
var vars:URLVariables = new URLVariables();
vars.html = data;
pdfUrl.data = vars;
navigateToURL(pdfUrl);
The problem is that it always sends as GET, and the data in vars.html is too long for my server to receive.
To make matters worse, it seems like AIR can only send GET via navigateToURL.
The issue with this is, I need to open a new browser window and send the POST data so that a script on my server can create a PDF file for the user.
What workarounds are there for this?
I'm not aware of any way to open a new browser window with a POST request, with GET being the default HTTP method used to open pages (which makes sense, really). An alternative, however, would be to POST the data using a simple HTTP request in AIR and once you get a response to the POST request in AIR, you can open a new browser window using a GET request.
So:
POST to your server directly from AIR.
Have your server return some kind of value that you can use in step 3.
Open a new browser window using navigateToURL and attach the value you got from step 2 to the URL.
This should work well, I think.
// Upload MP3-Byte-Array
private function uploadFile():void
{
var uploadURL:URLRequest = new URLRequest();
uploadURL.url = "myfile.php?var1=var1Value&var2=var2Value";
uploadURL.contentType = 'application/octet-stream';
uploadURL.method = URLRequestMethod.POST;
uploadURL.data = heavyDataThatyouWantToPass;
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
urlLoader.load(uploadURL);
}
private function completeHandler(event:Event):void
{
var loader:URLLoader = URLLoader(event.target);
}
myfile.php will be like this:
<?php
$var1 = $_REQUEST['var1Value'] ;
$var2 = $_REQUEST['var2Value'] ;
$heavyData = $GLOBALS[ 'HTTP_RAW_POST_DATA' ];?>