Saturday, October 6, 2012

Android + Erlang for Great Good: Cowboy Setup and Account Route

Please read Android + Erlang for Great Good: An Introduction if you haven't already done so.

Now that I've selected my webserver and defined my client its time to get started.  Since I don't know much about Erlang, Java or Android development I decided to start with a problem I'm VERY familiar with, all that standard account & authentication goop that you somehow have to rewrite every time you change languages, platforms etc.

Since my client is on an Android, we already have an authenticated user, we just need to somehow confirm their identity.  Fortunately the big players in the web have finally pretty much centered on the Oauth2 protocol to handle this problem.  What I need to do is pretty simple, get a token of some sort from the validating authority (in this case the players phone) and send that token + the players email address to my server.  My server can then validate the token via a call to a google server and return one of the following:
  • Invalid token: return 401 and note the oauth2 authority.
  • Token expired: return 401 and note the oauth2 authority.
  • Valid token, user does not exist: return 404.
  • Valid token, valid user: return 200 & json payload containing account details.

On the server side it looks like the account handler will need to become a standard REST + json resource, supporting GET, PUT and DELETE operations.  This post will walk through initial server setup and setup the route to /account.

Create a directory for this application and then copy the rebar script from basho into the new directory.  Next we'll want to create an application skeleton using ./rebar create-app appid=my_game.  This creates a very minimal app skeleton for you.

Now lets get cowboy integrated into our application.  For this we'll need to create a rebar.config file and put the following into it:

{deps, [
  {jiffy, ".*", {git, "git://github.com/davisp/jiffy.git", {branch, "master"}}},
  {cowboy, "0.6.1", {git, "git://github.com/extend/cowboy.git", {tag, "0.6.1"}}}
]}.
The jiffy dependency will come in handy later on when we need to encode/decode json.

./rebar get-deps will download these dependencies and ./rebar compile will compile them and your application code. We'll want to do this now to be sure we didn't make any mistakes thus far.

Now its time to define our application start point. When you start erlang with the -s file_name syntax erlang looks for a start/0 function within that file and executes it. We'll use the my_game_app.erl for this as well as the standard supervisor start/2, stop/1 functionality. Within start we'll need to start cowboy and my_game. The complete function is:
start() ->
  reloader:start(), %Makes debugging simple...
  ok = application:start(cowboy),
  ok = ssl:start(),
  ok = inets:start(),  
  ok = application:start(my_game).
inets and ssl are required when actually validating the auth token with google so we'll need to start both of them when our application is started as well.

Reloader is a very useful code snippet from the guys at Basho that allows for hot code upgrades within your running server.  This is particularly useful for debugging.  Simply add the erl file located here to your /src directory and going forward almost all code changes will be reloaded automatically whenever you ./rebar compile the app.  As far as I can tell, only changes to start/0 are not automatically reloaded as that particular method does not utilize the standard erlang supervisor pattern.

By default cowboy does nothing, so next we have to tell it about our end point.  This will simply be /account/email@address.com.  To set this up we need to edit the start/2 method. Putting it inside the start/2 method will allow us to upgrade the routes within the running server later on if needed. One more item to note is that cowboy uses binary strings so make sure you place << >> around your strings or the patterns will not match properly. The complete start/2 method looks like this:
start(_StartType, _StartArgs) ->
 Dispatch = [
  {'_', [
   {[<<"account">>, email], account_handler, []}
  ]}
 ],
 {ok, _} = cowboy:start_listener(http, 100,
   cowboy_tcp_transport, [{port, 8080}],
   cowboy_http_protocol, [{dispatch, Dispatch}]
  ),
 my_game_sup:start_link().

Finally lets setup our start.sh script to automate starting the server.  You can't actually run the server yet as the account_handler referenced by the dispatch does not yet exist, but you can start it up and get your first taste of error messages from the cowboy server.

Our start.sh is extremely simple and contains only the following line:
erl -pa ebin deps/*/ebin -boot start_sasl -s my_game_app

 Stay tuned for the actual account_handler implementation.

No comments:

Post a Comment