cURL call URLLoader and URLRequest mangling equivalent for all platforms

I have been trying to reproduce a working cURL call with openFL’s URLLoader and URLRequest without success for too long.

What I need is to reproduce the following call:

curl -X POST -H “Content-Type: application/json” -d ‘{ “appId”: “myAppID”, “apiKey”: “myAPIKey”, “user”: "[email protected]", “pass”: “myPassword”}’ https://myAPIURI.herokuapp.com/auth/issue-token

I have been trying all sorts of things in different order but cannot ever get a successful response.

Here is simplified dumbed down version of what I’m doing :

public function login(username:String, password:String)
{
    var url = "https://myAPIURI.herokuapp.com/auth/issue-token";     
    var request:URLRequest = new URLRequest(url);
   
    var variables = {"appId":"myAppID", "apiKey":"myAPIKey", "user":username, "pass":password };
    var urlVariables = new URLVariables(haxe.Json.stringify(variables));
    request.method = URLRequestMethod.POST;
    request.data = urlVariables;
    request.contentType = "application/json";

    var loader = new URLLoader();
    loader.addEventListener(Event.COMPLETE, successCallbackMethod);
    loader.addEventListener(ErrorEvent.ERROR, errorCallbackMethod);
    loader.addEventListener(IOErrorEvent.IO_ERROR, IOErrorCallbackMethod);
  
    loader.load(request);
}

And then one would simply call the login method like this:

login('[email protected]', 'myPassword');

I am trying to get this to work on all platforms starting with IOS, Android and Mac.
How on earth is this suppose to work ? Am I on the right track ? I’ve been at this for way too long.

I would try one of two things.

The first thing you could try is to set the “data” value as a String, directly. Use what you have already, set that as the “data” and see what happens.

Another thing I might try is to use URLVariables, like “var urlVariables = new URLVariables ()” then set the .appId to “myAppID”, etc, but perhaps this would not be as good because you definitely want it to be JSON. If the above does not work, also (maybe?) try adding the “Content-Type” header, manually.

Please let me know how it goes, thanks! :slight_smile:

Geez thanks for the answer, I really need to get this working soon.

As suggested I have tried the following methods:

...var urlVariables = new URLVariables();
urlVariables.appID = applicationID;
urlVariables.apiKey = apiKey;
urlVariables.user = username;
urlVariables.pass = password;
request.method = URLRequestMethod.POST;
request.verbose = true;
request.data = urlVariables;
    
var header = new URLRequestHeader("Content-Type", "application/json");
request.requestHeaders = [header];...

Logs out:

... Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Type: application/json
Content-Length: 122

* upload completely sent off: 122 out of 122 bytes
*   axtls_recv
*   axtls_recv
< HTTP/1.1 401 Unauthorized ...

Injecting headers do not reset the Headers completely but seem to concatenate instead… hence the doubled content-type.

If I still use the composition method for the URLVariables and set the content-type as a URLRequest property:

var urlVariables = new URLVariables();
urlVariables.appID = applicationID; ...
.... request.contentType = "application/json";  

I get:

... Accept: */*
Content-Type: application/json
Content-Length: 122
* upload completely sent off: 122 out of 122 bytes
*   axtls_recv
*   axtls_recv
< HTTP/1.1 400 Bad Request ...

If I use a simple string as data for the request, I get results that are quite similar.

...var variables = "{appId:"+applicationID+", apiKey:"+apiKey+", user:"+username+", pass:"+password+" }";
request.method = URLRequestMethod.POST;
request.verbose = true;
request.data = variables;
request.contentType = "application/json";...

Outputs:

...Accept: */*
Content-Type: application/json
Content-Length: 124

* upload completely sent off: 124 out of 124 bytes
*   axtls_recv
*   axtls_recv
< HTTP/1.1 400 Bad Request ...

Right now I’m thinking of using the lime cURL methods directly to send my calls, would that be a possibility ?

Try doing something like the last one, but don’t forget to include extra quotes in the string:

var variables = "{ \"appId\": \""+applicationID+"\", \"apiKey\": \""+apiKey+"\", \"user\": \""+username+"\", \"pass\": \""+password+"\" }";

Or I suppose it would be nicer with single quotes and Haxe string interpolation:

var variables = '{ "appId": "$applicationID", "apiKey": "$apiKey", "user": "$username", "pass": "$password" }';

OMG JOSHUA !!!

lol

How idiotic of me. I should have known the extra quotes weren’t legit.
Thanks a million. Really.

That did it. It now works and the show can go on.

Awesome! Great to hear :slight_smile:

For clarity’s sake and for folks struggling with calling a OAuth style restful API built with express, passport and nodejs, here is how I’ve finally connected to the API with an openFL built UI.

FIrst in, authentication:

private var authToken:String;

public function login(username:String, password:String) 
{
    var url = "https://myAPIURI.herokuapp.com/auth/issue-token";     
    var request:URLRequest = new URLRequest(url);
    
// Passing data as a string is your best bet here, also use haxe's String Interpolation and DO NOT waste time building your string by concatenating values as the interpreted value will surely hold lost quotes that will break your call. 

    var variables = '{ "appId": "$applicationID", "apiKey": "$apiKey", "user": "$username", "pass": "$password" }';
    request.method = URLRequestMethod.POST;
    request.data = urlVariables;
    request.contentType = "application/json";

    var loader = new URLLoader();
    loader.addEventListener(Event.COMPLETE, function(evt) 
          { 
              var data = haxe.Json.parse(evt.target.data);
              // grab your auth token from the data, the key name for this might change depending on your architecture.  
              authToken = data.token;
              getMyAppData();    
          });
    loader.addEventListener(ErrorEvent.ERROR, function(err) { trace("Error"); } );
    loader.addEventListener(IOErrorEvent.IO_ERROR, function(err) { trace("IOError"); } );

    loader.load(request);
}

Now add whatever method (in this case getMyAppData):

function getMyAppData(?vars)
{
    var request:URLRequest = new URLRequest(https://myAPIURI.herokuapp.com/MyURLMethodRoute); 
    request.requestHeaders = [new URLRequestHeader("Authorization", "Bearer "+authToken) ];
    request.method = URLRequestMethod.GET;
    request.contentType = "application/json";
    
    if(vars != null)
        request.data = vars;

    var loader = new URLLoader();
    loader.addEventListener(Event.COMPLETE, function(evt)
            {
                var data = haxe.Json.parse(evt.target.data);
               trace("SUCCESS ");
            });

    loader.load(request);
}

Edit: My wifi wasn’t connected on my device >.> Works perfectly on Android as well :slight_smile:

This kind of URLRequest thing works no problem on Mac, Flash and iOS. I can’t though seem to get it to work on Android. Keeps popping up an IO_Error. Should I be including a permission in the AndroidManifest file or…?