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_ACCEPT
request variable for possible response content types. The$accept_map
parameter 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 => xml
The purpose of this is to make response encoding decisions easier. When the HTTP
Accept
header 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
GET
body handler to implement record and collection indexing and retrieval.If a record id is present, the
$one
handler is called. Otherwise the$all
handler is called. Each are expected to return a response upon success. If no response is returned, an HTTP404
is returned instead. - post($post)
-
Adds an HTTP
POST
body handler to implement record creation.If a record id is present, an HTTP
400
is generated. Otherwise the request is dispatched to the handler in$post
which may return its own response. If no response is returned an HTTP400
will be generated if$meal->{grit}{id}
is not defined. Otherwise an HTTP <201> will be generated with theLocation
header set to the URL of the new resource. - put($old, $new)
-
Adds an HTTP
PUT
body handler to implement record modification and creation.If a record id is present, the
$old
hander is called. Otherwise the$new
handler 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 HTTP400
response is returned. Otherwise a redirect to the resource URL will be generated with the code set to201
for new records and302
for old records. - patch($one, $all)
-
Adds an HTTP
PATCH
body handler to implement record and collection patching.If a record id is present, the
$one
handler is called and is expected to generate a response upon success. An HTTP400
will be generated if the record id is removed from$meal->{grit}{id}
. An HTTP404
is generated if the handler does not generate a response.If no record id is present, an HTTP
404
will be returned if the handler in$all
is not defined. If a handler is defined, it will be called expecting to return a response. If no response is returned an HTTP400
is generated. - delete($delete)
-
Adds an HTTP
DELETE
body handler to implement record and collection deletion.If a record id is present, the
$one
handler is called and is expected to generate a response upon success. An HTTP400
will be generated if the record id is removed from$meal->{grit}{id}
. An HTTP404
is generated if the handler does not generate a response.If no record id is present, an HTTP
404
will be returned if the handler in$all
is not defined. If a handler is defined, it will be called expecting to return a response. If no response is returned an HTTP400
is generated.
SEE ALSO
AUTHOR
jason hord <pravus@cpan.org>
LICENSE
This software is information. It is subject only to local laws of physics.