NAME
WWW::Resource - Quickly create a REST style web service.
SYNOPSIS
package ResourceName;
use HTTP::Status
use WWW::Resource;
@ISA = qw( WWW::Resource );
sub GET {
return RC_OK, "Congratulations you have accessed this resource.";
}
ResourceName->run;
=EOF
In a browser:
http[s]://localhost/resourcename
Congratulations you have accessed this resource.
DESCRIPTION
This module ties together a small set of serializers and a FastCGI interface to a load balancer, in a convenient package allowing you to quickly deploy resources to the network with a bare minimum of coding. If you have installed a web server and configured it to use FastCGI - which takes about fifteen minutes if you use lighttpd - in about two more minutes you can expose a REST-style web service.
Userspace? No problem. SSL? No problem. Load balancing? Got it covered.
Please see "INSTALL.REST-FRAMEWORK" in the build directory for more info about the full system installation.
There are two ways to return your response to the caller (a browser or other program). You can simply return any Perl data structure, which will be serialized into the requested format (XML or JSON or "browser prettyprint" format), or you can actually construct a page yourself, perhaps even using CGI.pm to help, and return a single string. Any single string will be transmitted verbatim (after the headers) to the caller.
To access the resource via a browser or other program, decide which serialization format you want and add "format=xml" or "format=json" or "format=browser" to the query string part of the URI. For example, http://localhost/resourcename?format=browser.
Whenever you define a GET, PUT, POST, or DELETE function, those will be installed automatically as handlers. In fact you can override any HTTP method whatsoever, but in practice no one should need more than these for a REST style service. These functions will recieve as their only argument a hash reference to the parsed query string. For instance, the "format=browser" arg will be there, as well as any others. This is only for convenience, since these items are available through $ENV{QUERY_STRING}.
OVERLOADABLE METHODS
All HTTP methods are overloadable. In practice you will not need more than GET, POST, PUT, and DELETE.
In addition, ttl() and browserprint can be defined. ttl() should return a time-to-live value in seconds. Each of your processes will then exit after recieving a request after ttl has been exceeded, and the FastCGI process manager will start a new instance. Define browserprint() if you want to do your own pretty printing to the browser, ie when your service is called with format=browser. The default one is incredibly stupid.
EXAMPLE
Here is a fully functioning REST style web service, implementing all four CRUD operations (create retrieve update delete) via the analogous POST GET PUT DELETE http methods. This resource consists of all the PATH_INFO / QUERY_STRING pairs it has seen via previous requests, in the form of a hash.
package ResourceName;
use HTTP::Status
use WWW::Resource;
@ISA = qw( WWW::Resource );
my %resource = (); # no resources yet
# Time-to-live - default 1 hr - optional. You can
# also set this in the load balancer config file, but here
# is finer-grained control if you need it.
sub ttl { 60*60 };
# start the event loop
ResourceName->run;
# The above will run as-is, but won't do much.
# Create the following CRUD-analogous methods for different responses.
# "Retrieve"
sub GET {
# Return the specified value, if it exists
if(exists $resource{$ENV{PATH_INFO}}){
return RC_OK, $resource{$ENV{PATH_INFO}};
}
# No named resource specified? Return them all.
elsif($ENV{PATH_INFO}){
return RC_OK, \%resource;
}
# A named resource that's not there is an error
return RC_NOT_FOUND;
}
# "Update"
sub PUT {
my ($rkey, $rval) = ($ENV{PATH_INFO}, $ENV{QUERY_STRING});
if(exists $resource{$rkey}){
$resource{$rkey} = $rval;
return RC_UPDATED;
}
$resource{$rkey} = $rval;
return RC_CREATED;
}
# "Create"
sub POST {
my ($rkey, $rval) = ($ENV{PATH_INFO}, $ENV{QUERY_STRING});
$resource{$rkey} = $rval;
return RC_CREATED;
}
# "Delete"
sub DELETE {
my ($rkey, $rval) = ($ENV{PATH_INFO}, $ENV{QUERY_STRING});
if(exists $resource{$rkey}){
delete $resource{$rkey};
return RC_DELETED;
}
return RC_NOT_FOUND;
}
REQUIRES
A web server with FastCGI support, lighttpd is recommended. FCGI LWP JSON XML::Dumper
AUTHOR
Ira Woodhead, <ira at sweetpota dot to>
COPYRIGHT AND LICENSE
Copyright (C) 2006 by Ira Woodhead
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available.