NAME
Wurm::Grub::REST - Wurm::let grub for generating RESTful services.
SYNOPSIS
use Wurm qw(mob let);
use Wurm::Grub::REST;
use Data::UUID;
use JSON::XS;
use Tenjin;
my $grub = Wurm::Grub::REST->new
->get(
  sub {
    my $meal = shift;
    my $item = $meal->mind->{meld}{$meal->grit->{id}};
    return
      unless defined $item;
    $meal->grit->{item} = $item;
    return $meal->vent->{json}
      ? to_json($meal)
      : to_html($meal, 'item.html')
    ;
  },
  sub {
    my $meal = shift;
    $meal->grit->{items} = $meal->mind->{meld};
    return $meal->vent->{json}
      ? to_json($meal)
      : to_html($meal, 'index.html')
    ;
  },
)
->post(sub {
  my $meal = shift;
  my $text = $meal->req->parameters->{text};
  return
    unless defined $text;
  $meal->grit->{id} = gen_uuid($meal);
  $meal->mind->{meld}{$meal->grit->{id}} = $text;
  return Wurm::_302($meal->env->{PATH_INFO});
})
->patch(sub {
  my $meal = shift;
  return
    unless exists $meal->mind->{meld}{$meal->grit->{id}};
  my $text = $meal->req->parameters->{text};
  return
    unless defined $text;
  $meal->mind->{meld}{$meal->grit->{id}} = $text;
  return Wurm::_204;
})
->delete(sub {
  my $meal = shift;
  return
    unless exists $meal->mind->{meld}{$meal->grit->{id}};
  delete $meal->mind->{meld}{$meal->grit->{id}};
  return Wurm::_204;
})
;
sub gen_uuid {
  my $meal = shift;
  my $uuid = $meal->mind->{uuid};
  return lc $uuid->to_string($uuid->create);
}
sub to_html {
  my $meal = shift;
  my $file = shift;
  my $html = $meal->mind->{html}->render($file, $meal->grit);
  return Wurm::_200('text/html', $html);
}
sub to_json {
  my $meal = shift;
  my $json = $meal->mind->{json}->encode($meal->grit);
  return Wurm::_200('application/json', $json);
}
my $mind = {
  meld => {'Wurm::Grub::REST' => 'Hello, Wurm!'},
  uuid => Data::UUID->new,
  json => JSON::XS->new->utf8,
  html => Tenjin->new({
    path => ['./examples/html/rest'], strict => 1, cache => 0
  }),
};
my $app = Wurm::wrapp($grub->molt, $mind);
$app
DESCRIPTION
Wurm::Grub::REST is a Wurm::let to help build REST-enabled services. It provides a library of light-weight handler wrappers that attempt to conform to the REST protocol specification.
METHODS
Please see the documentation for Wurm::let for a description of super-class methods. Below is a list of overriden methods:
- new($accept_map)
 - 
Creates a new Wurm::let object with a gate handler installed that will inspect the
HTTP_ACCEPTrequest variable for possible response content types. The$accept_mapparameter can be used to specify a custom mapping between a mime-type and a key name that will be set in$meal->{vent}. If no map is given, a default map is installed with the following values:text/html => html application/json => json text/xml => xml application/xml => xmlThe purpose of this is to make response encoding decisions easier. When the HTTP
Acceptheader is set properly, this should allow you to do something like:sub handler { my $meal = shift; ... if ($meal->{vent}{json}) { return to_json($meal); } elsif($meal->{vent}{xml} ) { return to_xml ($meal); } elsif($meal->{vent}{html}) { return to_html($meal); } # no type handler installed; someone else's problem return; }The gate handler will also modify
$meal->{tube}by callingWurm::bend()assuming that any atom returned is an application record id. This is stored in$meal->{grit}{id}for further down-stream dispatching and access to the application. From the client point-of-view, this simply looks like:'http://.../path/to/rest'and
'http://.../path/to/rest/$id' - get($one, $all)
 - 
Adds an HTTP
GETbody handler to implement record and collection indexing and retrieval.If a record id is present, the
$onehandler is called. Otherwise the$allhandler is called. Each are expected to return a response upon success. If no response is returned, an HTTP404is returned instead. - post($post)
 - 
Adds an HTTP
POSTbody handler to implement record creation.If a record id is present, an HTTP
400is generated. Otherwise the request is dispatched to the handler in$postwhich may return its own response. If no response is returned an HTTP400will be generated if$meal->{grit}{id}is not defined. Otherwise an HTTP <201> will be generated with theLocationheader set to the URL of the new resource. - put($old, $new)
 - 
Adds an HTTP
PUTbody handler to implement record modification and creation.If a record id is present, the
$oldhander is called. Otherwise the$newhandler is called. Each are expected to return a response upon success. If no record id is present in$meal->{grit}{id}after calling the handler, an HTTP400response is returned. Otherwise a redirect to the resource URL will be generated with the code set to201for new records and302for old records. - patch($one, $all)
 - 
Adds an HTTP
PATCHbody handler to implement record and collection patching.If a record id is present, the
$onehandler is called and is expected to generate a response upon success. An HTTP400will be generated if the record id is removed from$meal->{grit}{id}. An HTTP404is generated if the handler does not generate a response.If no record id is present, an HTTP
404will be returned if the handler in$allis not defined. If a handler is defined, it will be called expecting to return a response. If no response is returned an HTTP400is generated. - delete($delete)
 - 
Adds an HTTP
DELETEbody handler to implement record and collection deletion.If a record id is present, the
$onehandler is called and is expected to generate a response upon success. An HTTP400will be generated if the record id is removed from$meal->{grit}{id}. An HTTP404is generated if the handler does not generate a response.If no record id is present, an HTTP
404will be returned if the handler in$allis not defined. If a handler is defined, it will be called expecting to return a response. If no response is returned an HTTP400is generated. 
SEE ALSO
AUTHOR
jason hord <pravus@cpan.org>
LICENSE
This software is information. It is subject only to local laws of physics.