Sending POST variables via an AIR application - actionscript-3

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' ];?>

Related

Sending data to a JSON with AS3

I've asked my client to share his database login and password but he can't give me full access to his database (security reason I suppose).
He told me to use a REST/JSON service that allows to post the data via this url with a specific key that allows him to identify all the datas coming from my app.
Here's what I did :
var urlRequest:URLRequest = new URLRequest("the_url_using JSON service");
urlRequest.method = URLRequestMethod.POST;
var urlvars: URLVariables = new URLVariables;
urlvars.observer_name = "Test Coco";
urlvars.observation_number = "5433";
trace("urlvars = "+urlvars);
urlRequest.data = urlvars;
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, onComplete);
urlLoader.load(urlRequest);
It's working, as it's sending the data, but the data format seems to be incorrect..
the url returns this error : "Observer name is Missing"
And the "trace (urlvars)" output :
urlvars = observer%5Fname=Test%20Coco&observation%5Fnumber=5433
So I think the problem come from the special character or something like that (as you can "observer_name" results by "observer%5Fname" and we can see a lot of %5")
Any idea how can I solve this ?
JSON string is a string representation of a generic object. Basically you go:
var anObject:Object =
{
"observer_name": "Test Coco",
"observation_number": 5433
};
or you can construct it
var anObject:Object = new Object;
anObject['observer_name'] = "Test Coco";
anObject['observation_number'] = 5433;
and then you convert it to String and attach to request
var jsonString:String = JSON.stringify(anObject);
urlRequest.method = URLRequestMethod.POST;
urlRequest.data = jsonString;
Read more about it: https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/JSON.html
Keep in mind that I don't know the specifics of that REST server of yours and the code above just might not work as it is. I only explain how to send a JSON string as a POST request.

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.

specifying the "request method" in externalinterface.call method?

When the user try to download the file ,i need to open a new html window and download the file , currently iam using "ExternalInterface.call" but i need to set the "requestmethod" otherwise server is throwing the error ,how to specify "requestmethod"?
Why not use the global navigateToURL method? You can pass in a URLRequest object which has a property called method and will solve your problem.
So you need something like this:
var request:URLRequest = new URLRequest("http://example.com");
request.method = URLRequestMethod.POST; // or anything you want
// parameters can be added to a URLVariables object
// which then can be set as requests data property
// example:
var params:URLVariables = new URLVariables();
params.username = "test";
params.password = "123";
request.data = params;
// load the page
// specify '_blank' parameter to open it in a new browser window
navigateToURL(request, "_blank");

URLRequest/URLLoader auto-converting POST request to GET

When I execute the following code:
var urlRequest:URLRequest = new URLRequest("http://somehost/with/some/path?andsomequerystring=true");
urlRequest.method = 'POST';
var urlLoader:URLLoader = new URLLoader(urlRequest);
urlLoader.addEventListener(Event.COMPLETE, function(event:Event):void{
trace('sweet');
});
It turns my explicit POST request to GET due to the presence of the querystring. If I remove the querystring (and serialize as part of the POST body), it successfully makes the corresponding POST request. Is there any way to prevent it from doing that? My server requires that a POST request be made with a querystring.
Ah think I found the answer, seems you have to specify a body as well or else it will still send as a GET request from their docs:
Note: If running in Flash Player and the referenced form has no body,
Flash Player automatically uses a GET operation, even if the method is
set to URLRequestMethod.POST. For this reason, it is recommended to
always include a "dummy" body to ensure that the correct method is
used.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/URLRequest.html#url
It is because the way you are having your url. If you want to have your variables for POST method you need to use URLVariables.
var urlRequest:URLRequest = new URLRequest(YOUR_REQUEST_URL_HERE);
var variables:URLVariables = new URLVariables();
variables.andsomequerystring = true;
urlRequest.data = variables;
urlRequest.method = 'POST';
var urlLoader:URLLoader = new URLLoader(urlRequest);
urlLoader.addEventListener(Event.COMPLETE, function(event:Event):void{
trace('sweet');
});

FileReference: post file without browsing

I am trying to upload a file to the server. I'm doing it like this:
var fileRef:FileReference = new FileReference();
fileRef.addEventListener(flash.events.Event.SELECT, selectHandler);
fileRef.addEventListener(flash.events.Event.COMPLETE, completeHandler);
fileRef.addEventListener(ProgressEvent.PROGRESS, normalprogressHandler);
fileRef.browse();
function selectHandler(event:flash.events.Event):void
{
var params:URLVariables = new URLVariables();
params.date = new Date();
params.ssid = "94103-1394-2345";
var request:URLRequest = new URLRequest("http://www.test.com/Uploads");
request.method = URLRequestMethod.POST;
request.data = params;
fileRef.upload(request, "Custom1");
}
function completeHandler(event:flash.events.Event):void
{
trace("uploaded");
}
function normalprogressHandler(event:ProgressEvent):void
{
var percent:Number = Math.floor((event.bytesLoaded * 100)/ event.bytesTotal );
trace(percent+"%");
}
Would it be possible to upload a file but without browsig for it? I want to decide myself what file to upload instead of the user performing a browse first
You can't do that with FileReference which has the following limitations (reference):
The load() and save() APIs can only be called in response to user
interaction (such as a button click).
The locations of the loaded and save files are not exposed to
ActionScript.
The APIs are asynchronous (non-blocking).
Clearly, it would represent a major security risk if the Flash player was arbitrarily allowed to upload anything from your local file system to a remote server.
If you're trying to upload from an AIR app, you can do what you're trying to do with the File class.