A web service using Mochiweb

This is the era of “apps”. The sheer number of them on various mobile devices is mind boggling. An app has to look good on the mobile device. But what about the backend. Will it scale if the app succeeds? How much effort should one put in for ensuring scalability upfront, e.g. by using as many cores and processors as are available? How hard would it be to write a web service in Erlang?

In this article, we will explore Mochiweb framework by creating a simple application where the web application gets a keyword and responds with a list of values.

The template engine we will use is ErlyDTL, which is an Erlang implementation of Django Template Language.

Getting started

We will experiment on Fedora 20. The steps are as follows:

  • Install erlang-mochiweb, erlang-erlydtl and erlang-rebar packages

  • Modify mochiwebapp.template in /usr/lib64/erlang/lib/mochiweb-2.4.2/support/templates/ to remove references to files not in the distribution – Makefile, .gitignore and rebar. The updated template will be:

%% -*- erlang -*-{variables, [{appid, "mochiwebapp"},
{author, "Mochi Media <dev@mochimedia.com>"},
{year, "2010"},
{version, "0.1"},
{port, 8080},
{dest, "{{appid}}"}]}.
{dir, "{{dest}}"}.
{template, "mochiwebapp_skel/src/mochiapp.app.src", "{{dest}}/src/{{appid}}.app.src"}.
{template, "mochiwebapp_skel/src/mochiapp.erl", "{{dest}}/src/{{appid}}.erl"}.
{template, "mochiwebapp_skel/src/mochiapp_app.erl", "{{dest}}/src/{{appid}}_app.erl"}.
{template, "mochiwebapp_skel/src/mochiapp_deps.erl", "{{dest}}/src/{{appid}}_deps.erl"}.
{template, "mochiwebapp_skel/src/mochiapp_sup.erl", "{{dest}}/src/{{appid}}_sup.erl"}.
{template, "mochiwebapp_skel/src/mochiapp_web.erl", "{{dest}}/src/{{appid}}_web.erl"}.
{template, "mochiwebapp_skel/start-dev.sh", "{{dest}}/start-dev.sh"}.
{template, "mochiwebapp_skel/priv/www/index.html", "{{dest}}/priv/www/index.html"}.
{file, "mochiwebapp_skel/rebar.config", "{{dest}}/rebar.config"}.
{chmod, 8#755, "{{dest}}/start-dev.sh"}.
  • Create a minimal app as follows

$ cd /usr/lib64/erlang/lib/mochiweb-2.4.2/support/
$ rebar create template=mochiwebapp dest=~/mochiwebx appid=mochiwebx
  • Test it

$ cd ~/mochiwebx
$ ./start-dev.sh

Open http://localhost:8080 in a web browser and you should see:
mochiwebx running.

Creating the Template

Create a directory templates in ~/mochiwebx. Create a template file templates/webapp.dtl with the following content:

<html>
<body>
<form method="GET">
<p>Key: <input type="text" name="key"></p>
<input type="submit">
</form>
{% for key,value in the_list %}
<p> {{ key }} Value {{ value }} </p>
{% endfor %}
</body>
</html>

We iterate over the elements of a list and display the values of each element in a row.

Erlang code

We need to add the code to process the request for the form. The function loop in the file src/mochiwebx_web.erl is the one which processes each request. We add a line to call a function as follows

loop(Req, DocRoot) ->
 "/" ++ Path = Req:get(path),
 try
   case Req:get(method) of
        Method when Method =:= 'GET'; Method =:= 'HEAD' ->
       case Path of

         "webapp" -> webapp(Req);

         _ ->

            Req:serve_file(Path, DocRoot)

       end;

(rest of the function as is)

We also add the function webapp to process the form and return the response as follows:

webapp(Req) ->
MyList = [{"a",1},{"b",2},{"c",3},{"a",4},{"b",5},{"a",6}],
Data = Req:parse_qs(),
Key = proplists:get_value("key", Data, "NONE"),
SendList = [ {X,Y} || {X,Y} <- MyList, X =:= Key ],
{ok, HTMLoutput} = webapp_dtl:render([{the_list, SendList}]),
Req:respond({200, [{"Content-Type", "text/html"}], HTMLoutput}).

In this simple example, we have used a hard-coded list and filtered it using a list comprehension and returned it in the same template.

JSON Response

An app on a mobile may not need an HTML page and it will be best to send a JSON response. We replace the call to render by a call to mochijson2:encode in webapp function as follows:

%%{ok, HTMLoutput} = webapp_dtl:render([{the_list, SendList}]),
HTMLoutput = mochijson2:encode(SendList),

The form will no longer be displayed but we can test it in a browser by using a url like

http://localhost:8080/webapp?key=a

Writing a web application using Erlang is not any harder. Even a trivial application is effortlessly scalable; so, Erlang is an option well worth exploring.

References

http://alexmarandon.com/articles/mochiweb_tutorial/

https://github.com/erlydtl/erlydtl/wiki

http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-1

Comments