Home > Tech Geek > Using Corona SDK with REST API Services

Using Corona SDK with REST API Services

People frequently ask on the Corona SDK forums about how to make their mobile apps connect with some Internet web service or if it’s even possible.  Corona SDK has various ways of interacting with Internet based services and depending on the service, you might want to use one over the other.

The three main ways that Corona SDK can communicate is broken down into three main categories:

  1. Socket communications.
  2. Synchronous Web Services.
  3. Asynchronous Web Services. 

Sockets are great for passing instantaneous data, like a multi-player game where what one player does on their device shows up almost immediately on their opponents computer.  Things like FTP and such would also tend to use sockets.  This is pretty low level programming and most people don’t want to get to that level.

This leaves us with Web based services.  In both cases, some webserver somewhere has a published API (Application Programming Interface) that defines how applications can interact with their services.    These API’s involve making a request to the server and then waiting for some response.

That waiting for a response can take time, so Corona SDK has two methods of waiting on the data:  Synchronous which means “Stop the app and wait until the data is done downloading” or Asynchronous which is “Hey, I need this data.. Let me know when it’s done and I’ll deal with it”.

In mobile apps, stopping and waiting on data, in particular if you’re downloading a large file like a photo, means your user can’t do anything else.  You generally don’t want to have your app “block” while waiting on data.  So we are going to focus on option 3 because it’s the simplest and easiest to work with.

Services will generally fall into three categories:  SOAP, REST and what I like to think:  Roll your own.  SOAP  or Simple Object Access Protocol is generally XML based and has overhead to start communications, maintain sessions and is generally not a simple approach despite the word “Simple” in it’s name.

REST or “Representational state transfer” on the other hand is generally easier to work with and can return data in the user’s choice of XML, JSON or other defined formats.

This tutorial is going to focus on a “Roll our own – based on REST” because, like SOAP, there is a lot to the server side of REST and frankly we don’t need that.  We just want to make a request and process the data and you don’t want to deal with the complexity of setting up a full REST service on your host. 

Before we get to the code here is what we are going to do.

On the server side, we are going to write a simple PHP based script to access a MySQL database to login a user to your server.  This script does nothing to create the user account nor are we going to go into setting up the database.

We are going to use HTTP GET requests to communicate with the server.  Sure in theory GET should be for getting things and POST for putting things, but in reality, GET is simpler and if your total data is less than 8Kbytes.

We are going to also use JSON to encode and decode our data so that it’s safe to transmit using HTTP requests.  This is  term called serialization.   We don’t need to know JSON.  We are going to let our PHP and Corona SDK libraries do the work for us.

So without further ado lets jump into some code.

SERVER SIDE

On the server side, we need some program that will process the HTTP GET request, contact a database, and then return some result to the application.  My language of choice is PHP for this and we are going to use a MySQL database.  This is probably the most common setup that almost every Web Hosting service offers to its customers.  You’re responsible for setting up your database, getting your database DSN (Data Set Name) or database name, the server name of the database (typically just the string “localhost”), and a Username/Password pair that lets your PHP script talk to your database.

You will need to setup a database with the following fields:

  • id — a integer (number) field, typically the Primary Index with an AUTOINCREMENT attribute.  Basically it’s a unique number for each user.
  • playername — you might want to call this username or userid.  Variable length character string probably 64 bytes long is good (VARCAR(64)).
  • password — another varchar string, 64 bytes long is sufficient.  We are going to use an MD5 hash process to one-way encrypt the passwords in the database, we won’t be using MySQL’s “Password” encryption.
  • Optional First and Last Names, again 64 byte varcar’s will be fine.
  • Last Login.  I’m old school unix guy, so I’m just going to make it an unsigned int and shove the unix time() number in the field.  MySQL offers a bunch of built in dates.  Don’t need them.

With that database setup and some accounts added, we are ready to go.  You probably should have some web page/form setup that lets users register for accounts and a PHP script that takes that form data and adds the users to the database, but that’s beyond the scope of this post.

Lets start by connecting to the database:

 PHP |  copy code |? 
01
02
<?php
03
define("DB_DSN",'yourdbname');
04
define("DB_HOST",'localhost');
05
define("DB_USER",'yourdblogin');
06
define("DB_PASS",'yourdbpass');
07
 
08
// Connecting, selecting database
09
$link = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die('Could not connect: ' . mysql_error());
10
mysql_select_db(DB_DSN) or die('Could not select database');
11
 
12
if(isset($_GET)) {
13
    $playername = base64_decode($_GET["playername"]);
14
    $password = base64_decode($_GET["password"]);
15
    $query = 'SELECT * FROM players WHERE playername="' . mysql_real_escape_string($playername) . '" or email="' . mysql_real_escape_string($loginid) . '"';
16
    $dbresult = mysql_query($query, $link);
17
    if (!$dbresult) {
18
        //echo "query failed";
19
        $result = array();
20
        $result["result"] = 403;
21
        $result["message"] = mysql_error();
22
        echo json_encode($result);
23
        mysql_free_result($dbresult);
24
        exit;
25
    }
26
    $player = mysql_fetch_array($dbresult, MYSQL_ASSOC);
27
    if (strcmp($player["password"],md5($password)) == 0) {
28
        $result = array();
29
        $result["result"] = 200;
30
        $result["message"] = "Success";
31
        $result["playername"] = $player["playername"];
32
        $result["firstname"] = $player["firstname"];
33
        $result["lastname"] = $player["lastname"]; 
34
        $query = sprintf("UPDATE players SET lastlogin=NOW() WHERE id=%s;", $player["id"]);
35
        $uresult = mysql_query($query, $link);
36
        if ($uresult) {
37
            //code if your update failed.  Doesn't really impact what we are doing. so do nothing.
38
        }
39
        echo json_encode($result);
40
    } else {
41
        //echo "password mismatch";
42
        $result = array();
43
        $result["result"] = 403;
44
        $result["message"] = "Forbidden";
45
        echo json_encode($result);
46
    }
47
} else {
48
    $result = array();
49
    $result["result"] = 400;
50
    $result["message"] = "Bad Request";
51
    echo json_encode($result);
52
}
53
exit;
54

This script defines our database parameters for accessing the database. Then it checks to see if the special PHP Array (or Table in Lua terms) called $_GET exists. If this script was executed as an HTTP GET request will will exist and each table entry contains each parameter passed to it.

Let’s look at what an HTTP GET request looks like. It’s basically a URL with some parameters tacked on to the end, such as:

So we have our server name and URL to run login.php. Then there is a question mark, which start’s a list of key-value pair parameters that will be passed. In this case we are passing a parameter named “playername” and it has a value of “my name”. Then an ampersand (&) separates the next key-value pair, in this case a parameter named password with a value of letmein.

You might be asking what is that %20 in the playername value. Well its the encoding for a space character. Your parameters must be “URL Encoded” before you pass them to the server if they have spaces or ther special characters in them. In our example, instead of using the standard urlecode/urldecode method, we are going to use a technique called “base64 encoding” because it produces a web-safe string that also hides the data (so our passwords are not sent in the clear).

Depending on what variables you need to send to the server, these URL strings can get quite long and complex. We are just going to be sending two to the server. These variables will be magically decoded into a PHP Associative Array called $_GET for us.

 PHP |  copy code |? 
1
2
if(isset($_GET)) {
3
    $playername = base64_decode($_GET["playername"]);
4
    $password = base64_decode($_GET["password"]);
5

We first check to make sure the table exists, then we create two PHP variables: playername and password from the $_GET table entries. Note that we are passing that data through PHP’s built in base64_decode() functions to decrypt the data we will be sending.

 PHP |  copy code |? 
01
02
    $query = 'SELECT * FROM players WHERE playername="' . mysql_real_escape_string($playername) . '" or email="' . mysql_real_escape_string($loginid) . '"';
03
    $dbresult = mysql_query($query, $link);
04
    if (!$dbresult) {
05
        //echo "query failed";
06
        $result = array();
07
        $result["result"] = 403;
08
        $result["message"] = mysql_error();
09
        echo json_encode($result);
10
        mysql_free_result($dbresult);
11
        exit;
12
    }
13

This block of code will query the database for the player’s record that matches that playername/password combination. Notice that we are calling a function “mysql_real_escape_string” on any string we send to the database. This is to protect against SQL Injection attacks where people send in SQL strings in an attempt to hack your database. Always escape any string sent to your database. User data cannot be trusted… Period…

If the query fails, we create a table called result, and add in some values to send back to your mobile app. The “echo json_encode()” will cause the table to be encoded into JSON magically for us and then the string is written out to the app.

This basic technique is how we are going to communicate with our app.

In the rest of the code, if the database query was successful, put the data from the query into a PHP table for us to use. Check to see if the password in the database matches ours (we are using md5() so we have to compare the database password with the results of md5(our password).

If that’s all good, build up a table called $result. Put whatever variables you want in the table. Then echo json_encode($result) the table and now your app should have data to use. If the passwords don’t match, send some result back to the app so it will know about the failure.

APP SIDE

We are going to use the Corona SDK network.request API call.

Using GET is pretty simple:

 Lua |  copy code |? 
01
02
local mime = require("mime")
03
local json = require("json")
04
 
05
local playerName = "fflintstone"
06
local password = "I<3Wilma!"
07
local URL = "http://yourserver.com/login.php?playername=" ..
08
      mime.b64(playerName) .. "&password=" .. mime.b64(password)
09
network.request( URL, "GET", loginCallback ) 
10

At this point, we’ve required in two modules we need, mime and json. For our example I’ve hard coded the player name and password into Lua variables.

Construct the URL which is a simple URL GET string and then pass that to network.request.

Since we are doing this asynchronous, your app will continue on doing whatever it was doing. Mean while it will wait until the server responds. When it does a function that you write called “loginCallback” that will then handle the result.

 Lua |  copy code |? 
01
02
    local function loginCallback(event)
03
        if ( event.isError ) then
04
            print( "Network error!")
05
        else
06
            print ( "RESPONSE: " .. event.response )
07
            local data = json.decode(event.response)
08
            -- do with data what you want...
09
        end
10
        return true
11
    end
12

At this point the Lua table “data” should contain entries for “result”, “message”, “playername”, “firstname” and “lastname” that we had set in the PHP script.

You could simply check:

 Lua |  copy code |? 
1
2
if data.result == "200" then
3
   -- player logged in okay
4
   print("Welcome back", data.firstname)
5
else
6
   -- prompt them to login again
7
end
8

At this point you know you’re logged in. It’s up to you to decide what data you need to pass and how to use it within your app.

Most REST services work this way. You make requests… you get back JSON or XML data. You will need to make sense out of the API documents of the service that you are using. Some will be easier to digest than others. For instance, PARSE seems to be pretty straight forward. Amazon’s SimpleDB made me ill trying to decode their API documents. But this is the basics. Have at it!

If you would like a complete Lua example, please check out the Corona Geek’s implementation at: https://github.com/CoronaGeek/Corona-SDK-JSON-Example

  1. Michael
    April 16th, 2012 at 10:54 | #1

    Nice post. Is the password sent in clear to the server or is it encrypted? How difficult would it be to implement an OAuth authentication in Corona?

  2. April 16th, 2012 at 12:12 | #2

    In my case, I am using a technique called Base64 encoding. The password (and username as well) are converted to what looks like a random string of letters and numbers. This is obscuring the password and anyone wanting it would have to go to extra steps to decode it. The encoding with Base64 is both common and simple to undo, so it’s not real encryption, just enough to make it “not in the clear”.

    You’re best practice would be to use https:// instead of http:// so that you get the native high grade encryption the browsers and web servers use.

    As for oAuth, I think its a pain. The need to call back to a web browser makes intergrating it with non-web services a bit more difficult. I’m hoping Ansca will come up with their own oAuth options at some point. I have heard there is an oAuth library in the community code, though I have not explored it.

  3. varun
    April 17th, 2012 at 07:59 | #3

    Hi

    I am developing a application using corona in which i wanted to access the database from the server. how can i do that?

    Please reply on my email if possible.

    Thanks & Regards
    Varun

  4. May 5th, 2012 at 21:35 | #4

    I’ve set everything up, the database with a players array and i have rows with all of the data you put it, id,player name, first name, last name, password, and last login. I try to run the code from the simulator and all i get is a blank RESPONSE: in the terminal, no errors or anything just a blank response. Any ideas what this could be?

  5. Alberto
    January 14th, 2013 at 06:44 | #5

    Hello Rob!
    A great post! Thanks a lot!

    I want to develop an app with Corona wich uses SQLite3:
    At server side I’m thinking in a MySQL database but it will have a lot of tables and registers.
    What’s the best method to get the MySQL’s data to my app side SQLite3’s data?

    Thanks in advance!

    Alberto.

  6. Mark
    March 3rd, 2013 at 03:27 | #6

    so do you have them pass in user and password for every dbase query with this api or do you store a session somehow?

  7. April 17th, 2013 at 06:04 | #7

    Hi would you mind stating which blog platform you’re working with? I’m looking to start my own
    blog soon but I’m having a difficult time making a decision between BlogEngine/Wordpress/B2evolution and Drupal. The reason I ask is because your layout seems different then most blogs and I’m looking for something completely unique.
    P.S My apologies for getting off-topic but I had to ask!

  8. April 17th, 2013 at 16:26 | #8

    WordPress.

  9. April 17th, 2013 at 16:31 | #9

    I’ve seen API’s do it all different ways. I think for simplicity, I have the username/password sent each time for the purpose of this tutorial, but in practice I would use some form of session management.

  10. tcatania
    May 21st, 2013 at 10:35 | #10

    I’m getting an error that says “Failure Cracking URL -” my URL with b64 ” – Network Error!”

    Any idea what this could be? I’m honestly lost on this one.

    Thanks!

  11. tcatania
    May 22nd, 2013 at 10:24 | #11

    @tcatania
    Seems like this is resolved, never mind. Thanks!

  12. plmarcot
    October 24th, 2013 at 12:54 | #12

    I had a probem on the LUA file.. Error Attemp to index local ‘data’ (a boolean value)
    Any help??

  13. Alexis
    December 28th, 2013 at 11:09 | #13

    Is it possible to use your example to download large files such as video or pdf ?
    I don’t want to user parse.com or ftp ?
    Regards

  14. December 28th, 2013 at 13:56 | #14

    It would be best to use the Corona SDK API call: network.download()

  15. February 11th, 2014 at 13:35 | #15

    is it possible to call wordpress data and used it in Corona? is there any sample that you can show me? in github?

  16. February 11th, 2014 at 20:20 | #16

    Not directly. It’s a MySQL database and you could write PHP to query the database. If you just want articles/posts, then you can get an RSS feed from WordPress and there is existing RSS code in the Corona code library to handle RSS feeds as well as the Business Sample App on Github.

  17. Babsam480
    May 18th, 2014 at 16:04 | #17

    Hey Rob, thanks for this instructions! Please, simulator is replying with the following runtime error “Attempt to index global ‘data’ (a nil value)” in regards to the following chunk of code “if data.result == “200” then”

    Thanks for your response.

  18. Sam
    June 2nd, 2014 at 10:02 | #18

    Hey Rob, please my browser is returning the following error.

    —-ERROR—-

    This will be fun!

    Notice: Undefined index: userid in /Applications/XAMPP/xamppfiles/htdocs/json.php on line 22

    Notice: Undefined index: password in /Applications/XAMPP/xamppfiles/htdocs/json.php on line 23
    {“result”:403,”message”:”No database selected”}
    Warning: mysql_free_result() expects parameter 1 to be resource, boolean given in /Applications/XAMPP/xamppfiles/htdocs/json.php on line 44

    ——–

    Please help me out of this ditch…

    Thanks!

  19. June 10th, 2014 at 14:23 | #19

    So what would be the most secure way to transfer data to a server from an app? I want to make a leaderboard for my game and publish it on my website and I don’t want somebody to change their score during this data transfer. I’m thinking to use a HTTP request with SSL.

  20. FunApp
    June 18th, 2014 at 17:41 | #20

    Hey Rob, good job on this tutorial. Please, how will the format of local host link look like. I did everything as you wrote but it won’t work.

    “07 local URL = “http://yourserver.com/login.php?playername=” .. ”

    Am assuming that the format of my local host path is not right. Please, what is the correct format if am running on local server?

    Thanks!

  21. June 18th, 2014 at 18:38 | #21

    Well I don’t know how your web server is setup on your computer so I don’t even want to speculate where your login.php should go, but it would be either:

    http://localhost/path/to/file.php
    or
    http://127.0.0.1/path/to/file.php

    Rob

  1. October 7th, 2013 at 16:17 | #1
  2. October 8th, 2013 at 08:28 | #2

%d bloggers like this: