--- layout: post summary: In which we see that it's easy to create REST interface with Dancer. title: Easily create REST interface with the Dancer 1.170 --- This week, with [Alexi](http://www.sukria.net/fr/)'s help, [I've been working on](http://github.com/sukria/Dancer) to add auto-(de)serialization to Dancer's request. This features will be available in the next [Dancer](http://perldancer.org/) version, the 1.170 (which will be out before April). The basic idea was to provides to developer a simple way to access data that have been send in a serialized format, and to properly serialize the response. At the moment, the supported serializers are : * Dancer::Serialize::JSON * Dancer::Serialize::YAML * Dancer::Serialize::XML * Dancer::Serialize::Mutable ## Configuring an application to use the serializer To activate serialization in your application: {% highlight perl %} set serializer => 'JSON'; {% endhighlight %} or in your configuration file: {% highlight yaml %} serializer: "JSON" {% endhighlight %} ## A simple handler Let's create a new dancer application (you can fetch the source on [GitHub](http://github.com/franckcuny/dancerREST) : {% highlight bash %} % dancer -a dancerREST % cd dancerREST % vim dancerREST.pm {% endhighlight %} then {% highlight perl %} package dancerREST; use Dancer ':syntax'; my %users = (); post '/api/user/' => sub { my $params = request->params; if ($params->{name} && $params->{id}) { if (exists $users{$params->{id}}) { return {error => "user already exists"}; } $users{$params->{id}} = {name => $params->{name}}; return {id => $params->{id}, name => $params->{name}}; } else { return {error => "name is missing"}; } }; true; {% endhighlight %} We can test if everything works as expected: {% highlight bash %} % plackup app.psgi & % curl -H "Content-Type: application/json" -X POST http://localhost:5000/api/user/ -d '{"name":"foo","id":1}' # => {"name":"foo","id":"1"} {% endhighlight %} Now we add a method to fetch a list of users, and a method to get a specific user: {% highlight perl %} # return a specific user get '/api/user/:id' => sub { my $params = request->params; if (exists $users{$params->{id}}) { return $users{$params->{id}}; } else { return {error => "unknown user"}; } }; # return a list of users get '/api/user/' => sub { my @users; push @users, {name => $users{$_}->{name}, id => $_} foreach keys %users; return \@users; }; {% endhighlight %} If we want to fetch the full list: {% highlight sh %} curl -H "Content-Type: application/json" http://localhost:5000/api/user/ # => [{"name":"foo","id":"1"}] {% endhighlight %} and a specific user: {% highlight sh %} curl -H "Content-Type: application/json" http://localhost:5000/api/user/1 # => {"name":"foo"} {% endhighlight %} ## The mutable serializer The mutable serializer will try to load an appropriate serializer guessing from the **Content-Type** and **Accept-Type** header. You can also overload this by adding a **content_type=application/json** parameter to your request. While setting your serializer to mutable, your let your user decide which format they prefer between YAML, JSON and XML. ## And the bonus Dancer provides now a new method to the request object : `is_ajax`. Now you can write something like {% highlight perl %} get '/user/:id' => sub { my $params = request->params; my $user = $users{$params->{id}}; my $result; if (!$user) { _render_user({error => "unknown user"}); } else { _render_user($user); } }; sub _render_user { my $result = shift; if (request->is_ajax) { return $result; } else { template 'user.tt', $result; } } {% endhighlight %} If we want to simulate an AJAX query: {% highlight bash %} % curl -H "X-Requested-With: XMLHttpRequest" http://localhost:5000/user/1 {% endhighlight %} and we will obtain our result in JSON. But we can also test without the X-Requested-With: {% highlight bash %} % curl http://localhost:5000/user/1 {% endhighlight %} and the template will be rendered. Hope you like this new features. I've also been working on something similar for [Tatsumaki](http://github.com/miyagawa/tatsumaki).