API Request with adobe AIR - actionscript-3

I am trying to consume delicious api in adobe AIR AS3 project described here: https://github.com/avos/delicious-api
particularly the suggest api (/v1/posts/suggest) described at the end of this page: https://github.com/avos/delicious-api/blob/master/api/posts.md
In debug mode the app asks for username and password and keeps asking it even after providing valid username and password and never tracing the response. I have no idea what's going wrong here. Below is my code:
var request:URLRequest = new URLRequest("https://api.del.icio.us/v1/posts/suggest?red=api&url=http%3A%2F%2Fyahoo.com");
request.method = URLRequestMethod.POST;
//encoded string using as3 class at https://github.com/MoritzStefaner/revisit/blob/master/lib/com/hurlant/util/Base64.as
var encoded:String = Base64.encode("validusername:validpassword");
trace(encoded);
var credsHeader:URLRequestHeader = new URLRequestHeader("Authorization", "Basic " + encoded);
request.requestHeaders.push(credsHeader);
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, handleResults);
loader.load(request);
function handleResults(evt:Event):void
{
var response:String = evt.target.data as String;
trace("response:" + response);
}

From taking a brief look at the linked API, none of the methods suggest support for authentication information being sent as part of the POST body (which is what your code is doing). So unless that is documented somewhere else, you are using the API incorrectly. It's also reasonably rare to see an HTTP POST combined with a QueryString (which is again what your code above is doing) so that is a little odd.
I think Delicious just needs HTTP Basic auth, which is covered in an SO question here.

Related

sending a GET request from a banner

I have to build a banner where people fill a form with their name and email send when they click, we send the data in order to send them back a brochure instantly.
I am not a dev, so it is a little bit confusing for me and I hope my explanations will be clear enough.
Apparently, the website only accept POST request but we cannot send like that from the banner due to crossdomain issue. So the request has to be send as a GET.
We found this website which does the conversion:
http://get-to-post.nickj.org/
for the purpose of the test, everything is hardcoded. When we test, this url:
http://get-to-post.nickj.org/?http://www.vikingrivercruises.co.uk/Forms/SaveRequestBrochures?InquiryReason[0]=2351&InquiryMessage[0]=UK+River+Brochure+Download&InquiryType[0]=Brochure-d&InquiryReason[1]=1450&InquiryMessage[1]=UK+Brochure+Requests+%28from+web%29&InquiryType[1]=Brochure&BrochureCode=UKBR15&SelectedBrochuresDeliverability=UKBR15+mail-yes+ebrochure-yes&selectedBrochures=UKBR15&Title=Mr.&FirstName=Andrew&LastName=Davies&EmailAddress=nicom21a%40gmail.com&PhoneNumberString=098921313132312&Country=United+Kingdom&OtherCountry=&Address1=&Address2=&Address3=&City=&State=&OtherState=&Zip=&EmailMeSpecialOffers=true&FriendTitle=&FriendFirstName=&FriendLastName=&FriendEmailAddress=&RedirectUrl=http%3A%2F%2Fwww.vikingrivercruises.co.uk%2Fbrochures%2Frivers-brochure-thank-you.html
and copy past it in the browser, it works perfectly and we receive a brochure instantly, but when I try to replicate it from the banner it doesn't work.
Here is my code, many thanks
var requestVars:URLVariables = new URLVariables();
requestVars.link = 'InquiryReason[0]=2351&InquiryMessage[0]=UK+River+Brochure+Download&InquiryType[0]=Brochure-d&InquiryReason[1]=1450&InquiryMessage[1]=UK+Brochure+Requests+%28from+web%29&InquiryType[1]=Brochure&BrochureCode=UKBR15&SelectedBrochuresDeliverability=UKBR15+mail-yes+ebrochure-yes&selectedBrochures=UKBR15&Title=Mr.&FirstName=Andrew&LastName=Davies&EmailAddress=nicom21a%40gmail.com&PhoneNumberString=098921313132312&Country=United+Kingdom&OtherCountry=&Address1=&Address2=&Address3=&City=&State=&OtherState=&Zip=&EmailMeSpecialOffers=true&FriendTitle=&FriendFirstName=&FriendLastName=&FriendEmailAddress=&RedirectUrl=http%3A%2F%2Fwww.vikingrivercruises.co.uk%2Fbrochures%2Frivers-brochure-thank-you.html'
var request:URLRequest = new URLRequest();
request.url = 'http://get-to-post.nickj.org/?http://www.vikingrivercruises.co.uk/Forms/SaveRequestBrochures';
request.method = URLRequestMethod.GET;
request.data = requestVars;
for (var prop:String in requestVars) {
trace("Sent " + prop + " as: " + requestVars[prop]);
}
var loader:URLLoader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, loaderCompleteHandler);
loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
I also tried like that
request.url = 'http://get-to-post.nickj.org/?http://www.vikingrivercruises.co.uk/Forms/SaveRequestBrochures?';
I think there are many points in your case that should be clarified :
If you want send a URL request to a server, but ignores any response, and I think this is your case because you can't get response, It's better to use sendToURL instead of URLLoader.load().
If you test your swf on line, you will get a security error because the used site(http://get-to-post.nickj.org/) doesn't have a crossdomain.xml file to get authorization to execute the URL : http://get-to-post.nickj.org/?http://www.example.com/?param=value.
Even when you execute your sendToURL successfully, you have another problem because the site that you have mentioned, which convert GET request to a POST one, will not do the job because it's creating a page with a POST form with your data and submitting it when the page is loaded which is never fired with flash.
So, I think it's better to see the crossdomain problem with your target site (vikingrivercruises) to give you authorization to send POST data. And if It's always impossible, try to set another URL (site) that get your GET data and send it via curl, for example, to your destination.

search embeded webpage source in vb.net

I wrote a program that includes an embedded web browser that loads a website which have a changing part (the part changes about 2 times a week and it have no regular timing pattern) that I want to search for a particular part in the opened webpage source code after refreshing the webpage in a specified time interval.
I found many things similar to my question but this is what I want and those questions doesn't have:
search embedded webpage source (they searching the webpage without embedding, and I had to embed it because I had to login before I see the particular page)
so this is the procedure I'm trying to do:
1- open a website in embedded web browser
2- after user logged in, with a press of button in program, it hides the embedded
web browser and start to refresh the page in a time interval (like
every minute) and search if the particular code changed in the source of
that opened webpage
any other/better Ideas appreciated
thanks
Many years ago I wrote an app to reintegrate forum posts from several pages into one and I struggled with the login issue too and thought it was only possible using an embedded browser. As it turns out, it's possible to use System.Net in .NET to handle web pages that need a login as you can pull the cookies out and keep them on hand. I would suggest you do that and move away from the embedded browser.
Unfortunately I wrote the code in C# originally, but as it's .NET and is mostly classes-based, it shouldn't be too difficult to port over.
The Basic Principle
Find out what information is included in the POST when you login, which you can do in Chrome with developer mode on (F12). Convert that to a byteArray, POST it to the page, store the cookies and make another call with the cookie data later on. You will need a class variable to hold the cookies.
Code:
private void Login()
{
byte[] byteArray = Encoding.UTF8.GetBytes("username=" + username + "&password=" + password + "&autologin=on&login=Log+in"); // Found by investigation
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("yourURL");
request.AllowAutoRedirect = false;
request.CookieContainer = new CookieContainer();
request.Method = "POST";
request.ContentLength = byteArray.Length;
request.ContentType = "application/x-www-form-urlencoded";
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse response = request.GetResponse();
if (((HttpWebResponse)response).StatusCode == HttpStatusCode.Found)
{
// Well done, your login has been accepted
loginDone = true;
cookies = request.CookieContainer;
}
else
{
// If at first you don't succeed...
}
response.Close();
}
private string GetResponseHTML(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AllowAutoRedirect = false;
// Add cookies from Login()
request.CookieContainer = cookies;
request.ContentType = "application/x-www-form-urlencoded";
WebResponse response = request.GetResponse();
string sResponse = "";
StreamReader reader = null;
if (((HttpWebResponse)response).StatusCode == HttpStatusCode.OK)
{
reader = new StreamReader(response.GetResponseStream());
sResponse = reader.ReadToEnd();
reader.Close();
}
response.Close();
return sResponse;
}
Hope that helps.
I had to change to C# and I found what I was looking for:
string webPageSource = webBrowser1.DocumentText;
That gave me the source of web page opened in webBrowser1 control.

SoundCloud POST Comment Not Authorized

[UPDATE]
Problem fixed. Working code and method updated below!
So, I am trying to post a comment to a SoundCloud track using the SoundCloud api in AS3.
The documentation can be found here:
http://developers.soundcloud.com/docs/#comments
And my code is as follows:
var urlLoader:URLLoader = new URLLoader();
var urlString:String = "https://api.soundcloud.com/tracks/" + soundModel.currentlyPlayingItem.id + "/comments.json" + "?comment[body]=" + commentString + "&comment[timestamp]=" + trackPositionComment;
var urlRequest:URLRequest = new URLRequest(urlString);
urlRequest.method = URLRequestMethod.POST;
var variables:URLVariables = new URLVariables();
variables.oauth_token = soundModel.userToken; //here is the filler variable to make POST, not GET.
urlRequest.data = variables;
urlRequest.contentType = "application/x-www-form-urlencoded";
var header2:URLRequestHeader=new URLRequestHeader("oauth_token",soundModel.userToken);
var header3:URLRequestHeader=new URLRequestHeader("client_id", "sdjhb4jhbkjbe4gkjbh4random");
urlRequest.requestHeaders.push(header2);
urlRequest.requestHeaders.push(header3);
urlLoader.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, commentPosted);
urlLoader.load(urlRequest);
Originally I was consistently getting a 401 - unauthorized error.
After playing around with the SoundCloud API console, I saw that there was a 'content-length' of 0, meaning no body. So all the authentication stuff had to be going in headers, not variables. However, with POST method in AS3 UrlLoader, it will automatically send as a GET if there is no body (variables) included. So for that reason I left an arbitrary variable value.
Also the two parameters, 'body' and 'timestamp' indeed have to be sent as 'comment[body]' and 'comment[timestamp]' even though this isn't quite made clear in the documentation. Also both of these parameters have to be included in the URL, and not as variables or headers.
Finally, to get a authorized return, you must provide both your 'client_id' and 'oauth_token' as headers.
It was this magic combination that did it for me. I hope this helps some other people, ready to rip their hair out like I was.
Thx,
Theo M.

Flex: Export Excel via Servlet

I want a user to press an excel button and get prompted to download an excel file. I normally do it like this:
var dest:String = excelEndpoint;
var request:URLRequest = new URLRequest();
request.url = dest;
fr.download( request,'Locates.xls' );
fr.addEventListener(HTTPStatusEvent.HTTP_STATUS, handleStatus);
fr.addEventListener(IOErrorEvent.IO_ERROR, handleErr);
However, now I need to pass an object to the servlet. Seeing that you can't do that with URLRequest I tried using HTTPService:
var service:HTTPService = new HTTPService();
service.url = excelEndpoint;
service.method = "POST";
service.showBusyCursor = true;
service.addEventListener("result", httpResult);
service.addEventListener("fault", httpFault);
service.send( myObject);
Now I can get my data (myObject) to the servlet successfully, but I don't get prompted for a download.
How can I do that? Is it even possible with HTTPService?
Thanks for any helpful tips.
I don't think there is anything you can do w/ a remote request from the Flash Player to prompt the user to download something. The way I have done this in the past is two fold:
Remote request pings server that generates the excel file and saves it to a temporary directory. The request returns a URL to the Flex app as the result of the call.
When Flex app gets the result--a URL--it creates a URL request and pops it open in a new window, prompting the user to download the generated excel sheet.
I don't see a way to do this in one shot; because the return value from the Flex HTTPService call goes to the Flash Player, not the browser.
SOLVED:
I wanted to accomplish this with 1 remote call and the way I found to do this while passing an object that contained collections is this:
var uv:URLVariables = new URLVariables();
uv.typesColl = myObj.types.toString();
uv.partiesColl = myObj.parties.toString();
uv.statuses = myObj.statuses.toString();
Basically, create a property on the URLVariables object for each collection and then set all collections toString();
Hope that helps someone.

Reading server error messages for a URLLoader

I have an URL loader with the following code:
public function getUploadURL():void {
var request:URLRequest = new URLRequest();
var url:String = getPath();
// Adds time to prevent caching
url += "&time=" + new Date().getTime();
request.url = url;
request.method = URLRequestMethod.GET;
_loader = new URLLoader();
_loader.dataFormat = URLLoaderDataFormat.TEXT;
_loader.addEventListener(Event.COMPLETE, getBaseURL);
_loader.addEventListener(IOErrorEvent.IO_ERROR, onGetUploadURLError);
_loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, getHttpStatus);
_loader.load(request);
}
My problem is that this request might be wrong, and so the server will give me a back a 400 Bad Request, with a message to explain the error. If the Event.COMPLETE, I can see some message (a response) back from the server in the "data" field of the Event, but if onGetUploadURLError or getHttpStatus is called, it just says that the error code is 400 but does not show me the message associated with it.
The "data" field is undefined in getHttpStatus and it is "" in onGetUploadURLError.
On the contrary, in getBaseURL, I get: {"ResponseMetadata":{...}}
I checked and I do get a similar response in my browser for a wrong request, but I cannot see it.
Any idea how I can please get the message?
Thank you very much,
Rudy
Flash does not handle HTTP status codes very well. Here is a blog post with comments from an Adobe employee saying the problem is actually the plug-in limitations. The Adobe employee points to a library for doing HTTP requests using AS3 through sockets but I doubt that would be highly efficient (compared to having the plugin-in hand requests off to the browser).
Standard practice on all projects I have ever worked on was to always send a 200 OK and add a error key onto the message.
edit: also see this bug which is exactly your issue.