Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Gideros REST API library — Gideros Forum

Gideros REST API library

ndossndoss Guru
edited May 2012 in Code snippets
I updated the REST API library I was working on (it was initially mentioned in http://www.giderosmobile.com/forum/discussion/comment/6392). I haven't finished it by any means but it's a little bit cleaner now and supports a few other APIs (initially it only had GameMinion support -- now it has limited support for redmine & vanilla forum).

The source for the library is at: https://github.com/KosiDossApps/gideros_restful_apis

A lua or json data file can be used to describe an API. An entry for a method looks like so:
registerUser = { 
  path = "users.json",
  required_params = { "first_name", "last_name", "username", "email", "password" },
  optional_params = {
     "profile_picture", "points" ,
     "facebook_id", "facebook_enabled", "facebook_access_token",
     "twitter_enabled ", "twitter_enabled_token",
  },                               
  method = "POST",
},
The same method described using json would be:
"registerUser" : { 
    "path" : "users.json",
    "required_params" : [ "first_name", "last_name", "username", "email", "password" ],
    "optional_params" : [
        "profile_picture", "points" ,
        "facebook_id", "facebook_enabled", "facebook_access_token",
        "twitter_enabled ", "twitter_enabled_token"
    ],
    "method" : "POST"
},
The above method is part of the GameMinion API. To call it, you'd first instantiate the GameMinion class:
-- access and secret key are given to you when you sign up for GameMinion and create a new game
gm = GameMinion.new(accessKey, secretKey)
An example call to the registerUser function would then look something like:
gm:registerUser("Atilim","Cetin","atilim","atilim@somewhere.com","password")
If you want to pass optional arguments, you'd add a table w/ the arguments to the end of the argument list like so:
gm:registerUser("Atilim","Gorkem","atilim","atilim@somewhere.com","password", { points=7 })
The general structure of a function is:
object:method(requiredArg1, requiredArg2, ..., requiredArgN, optionalArgTable, callbackTableOrFunctionNil)
For example, here's a very simple API call from the GameMinion API. There aren't any required or optional arguments:
        "getNews" : {
            "path" : "news.json",
            "method" : "GET",
            "authentication" : true
        },
In this case, the call would be either:
gm:getNews()
gm:getNews(callback)
All calls are asynchronous. If no callback is provided, a default callback is used -- the default behavior is to print an error message on a failed call and print out the lua table in the response if successful. Callbacks can be specified in a couple of different ways:

1. A function that takes the response object (e.g., function(response) .... handle response .... end)
2. A table with an error and/or success functions(e.g., { error=function(response) ... end, success=function(response) ... end }). The error and success functions are optional.

Here's an example:
gm:getNews(function(r) 
   if r.error then
       print("I couldn't get the news")
   else
      print("I got the news!") 
end)
 
-- OR
 
gm:getNews({
   error = function(r)   print("I couldn't get the news") end
   success = function(r)   print("I got the news!") end
})
Responses have the following structure:
     response.error  -- true/false ... true if there's an error
     response.data   -- lua table w/ response data
     response.url      -- url used to make the REST call
+1 -1 (+6 / -0 )Share on Facebook

Comments

  • ar2rsawseenar2rsawseen Maintainer
    So basically, wrapping new API in Gideros is a matter of simply creating a json configuration file.

    That is so cool. :)
  • So basically, wrapping new API in Gideros is a matter of simply creating a json configuration file.
    These links are where the idea came from: http://fperrad.github.com/lua-Spore/
    and https://github.com/SPORE/api-description.

    The description can also be a lua file (the GameMinion API has both -- as an example).

    Everything is mostly handled by the json file, except for Authentication.
  • @ndoss, thanks for this additional description (and the REST library in general). I was having a bit of trouble deciphering your previous example but this info seems to make it much clearer.

    Best regards
  • atilimatilim Maintainer
    edited May 2012
    whoa! it's simply great. I like every piece of your API design.
  • Great job, really impressive quality.
  • ndossndoss Guru
    edited May 2012
    @bowerandy pointed out that I left in the secret keys (thanks again, I appreciate you looking out for me!).

    In the original thread, (sneaky) @avo had questioned: "It seems to me that for things like this, with logins or api keys etc, that not being able to encrypt lua files will be a big problem? Or is there a way around this?"

    His question made me realize that there's little harm in putting the keys in the game. Someone could "cheat" and give themselves achievements and perform various other acts of mischief, but they can't do all that much harm. So ... I decided to put the keys into the example.

    The keys are associated with the "gideros_example" game that I created. When you get an account w/ @GameMinion, it lets you create games ... each game gets two unique keys. The keys can be used to interact with the game database in limited ways (e.g., they don't allow people to log into your GameMinion account).

    Oh and thanks @atilim and @GameMinion for the kind words :).

    --ND
  • avoavo Member
    Yes it's good that it's not dangerous for the keys to be out thank you for looking into that @ndoss.

    I still think that if someone can send whatever data they want they could harm the user experience of your app for others, by ruining the leaderboard, or cheating if it's a multiplayer game. I could be mistaken again of course, and I'm not sure how non-lua apps handle this either.

    Oh and @ndoss AMAZING! I think I have another update to add to the site :P
  • Could we not at least do the b64enc(accessKey..":"..secretKey) inside a plugin, perhaps also encoded with a hash of the contents of the resource files in the game? I think we'll need to do something to at least discourage the casual hacker.

    Does anyone know how Moai Cloud handles this sort of security issue?

    Best regards
  • Just saw this article which discusses this very issue.
    http://blog.programmableweb.com/2012/05/07/cloud-api-security-panel-at-infosec/

    Likes: avo

    +1 -1 (+1 / -0 )Share on Facebook
  • This is something we have thought long and hard about and at the end its a matter of balance between security and usability.

    The Game Access and Secret Keys being readable still isn't really a problem as most actions are associated with a particular user, which also has to be authenticated. So a malicious user who has your game's keys can at most submit high scores, unlock achievements etc... All of which are associated with a particular user, which we (or the developer) can ban.

    Obviously this doesn't prevent the malicious user from trolling the dev and just creating loads of fake users and flooding the leaderboards with nonsense, but then that becomes a web API abuse issue and we'll handle that separately (throttling, IP banning etc...).

    Likes: avo

    +1 -1 (+1 / -0 )Share on Facebook
  • joelghilljoelghill Member
    edited August 2012
    Hey all,

    I'm having some trouble implementing the login feature for the Game Minion API. Here's my code:
    --logs in the user
    -- accepts table with email and password
    -- returns auth_token
    function loginUser(t)
    -- Login 
    	r = gm:login(t[1], t[2], function(r)
    		if r.error == true then
    			print("Login failed")	
    		else 
    			print("login worked") 
    			print(r.data.auth_token) 
    		end
    		end
       )
    end
    No matter what arguments I enter into gm:login(), it always seems to print "login worked" and prints nil for r.data.auth_token. What am I doing wrong here? I would like to have more logic associated with the failure and success states of the function.
  • Yeah, it seems like gm:login() is always considered successful when I add callback functions. When I do not ad a callback, it behaves as normal, but I do not know how to get the auth_token without the use of a callback function.
  • Hey guys,

    This thing is really interesting. My team is going to take a look at it too.
    Why let it stop here? C'mon :)
  • SinisterSoftSinisterSoft Maintainer
    Is this plugin fully cross platform?

    Could this be improved to add 'parse.com' to the list?
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
Sign In or Register to comment.