The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

    REST::Resource      -- Provide base class functionality for RESTful servers.

SYNOPSIS

    package My::Rest::Resource;
    use base "REST::Resource";

    sub new
    {
        my( $class )    = shift;
        my( $this )     = $this->SUPER::new( @_ );
        $this->method( "PUT",   \&Create, "This method handles the creation of My::Rest::Resource." );
        $this->method( "GET",   \&Read,   "This method handles the reading of My::Rest::Resource." );
        $this->method( "POST",  \&Update, "This method handles the updating of My::Rest::Resource." );
        $this->method( "DELETE",\&Delete, "This method handles the deletion of My::Rest::Resource." );
    }

    sub Create  { my( $this ) = shift;  my( $request_interface_instance ) = shift; ... }
    sub Read    { my( $this ) = shift;  my( $request_interface_instance ) = shift; ... }
    sub Update  { my( $this ) = shift;  my( $request_interface_instance ) = shift; ... }
    sub Delete  { my( $this ) = shift;  my( $request_interface_instance ) = shift; ... }

    package main;
    use My::Rest::Resource;

    my( $restful )      = new My::Rest::Resource();
    $restful->handle_request();                         ## One-shot CGI Context

DESCRIPTION

    This is a fork of WWW::Resource 0.01.  The major changes are:

    [] Full OO implementation
    [] Overt abstract base class design
    [] Support of Perl 5.6
    [] Support for use with CGI interface.
    [] Support for HEAD and TRACE.
    [] Method / handler registration to better support
       application-semantics over REST-semantics.

METHOD REGISTRATION

HTTP method handlers should be members of your derived class and expect $this (or $self) as the first parameter.

    sub Create  { my( $this ) = shift;  my( $request_interface_instance ) = shift; ... }
    sub Read    { my( $this ) = shift;  my( $request_interface_instance ) = shift; ... }
    sub Update  { my( $this ) = shift;  my( $request_interface_instance ) = shift; ... }
    sub Delete  { my( $this ) = shift;  my( $request_interface_instance ) = shift; ... }

REQUEST INTERFACE INSTANCE

$request_interface_instance is a wrapper for your favorite Common Gateway Interface implementation. Mine is CGI.pm for server-side request interrogation and server-side response.

If you don't like this, create a class modeled after REST::Request and register it with:

    my( $restful ) = new REST::Resource( request_interface => new My::REST::Request() );

The REST::Resource constructor will validate that My::REST::Request implements the requisite methods new(), http(), param() and header() and then only use these methods to interace with the Common Gateway Interface variables.

REQUESTED RETURNED CONTENT-TYPE:

The requesting client is responsible for specifying the returned Content-Type: header in one of two ways.

[] Via the "Accept: application/xml" HTTP header. [] Via the CGI query parameter ?format=xml

The Accept: header is preferred as it is semantically cleaner, but the CGI query parameter is also supported in recognition of the fact that sometimes it is easier to affect the request URL than it is to get at and specify the HTTP headers.

DEFAULT SUPPORTED CONTENT TYPES

The supported content types provided by the base class are:

[] ?format=xml or Accept: application/xml [] ?format=json or Accept: text/javascript [] ?format=html or Accept: text/html

HTML will be returned if the requestor appears to be a browser and no format is specified.

XML will be returned if the requestor does NOT appear to be a browser and no format is specified.

AUTHOR

frotz@acm.org Fork of WWW::Resource into REST::Resource.

CREDITS

Ira Woodhead <ira at sweetpota dot to> For his WWW::Resource implementation.

BUGS

In the spirit of Transparency, please use rt.cpan.org to file bugs. This way everyone can see what bugs have been reported and what their status is and hopefully the fixed-in release.

METHODS

new()

USAGE:

    my( $restful ) = new REST::Resource();
    $restful->method( "GET", \&get_handler );
    $restful->handle_request();

    my( $restful ) = new REST::Resource( request_interface => new REST::Request() );

DESCRIPTION:

Create an instance of a REST::Resource, or one of its derived classes.

If you need a specific implementation of the REST::Request interface, pass it in as shown in the second constructor call.

run() CAUTION

USAGE:

    my( $restful )      = new REST::Resource( request_interface => new REST::RequestFast() );
    $restful->run();

    my( $restful )      = new Your::WWW::Resource::Implementation( new REST::RequestFast() );
    $restful->run();

DESCRIPTION:

This method will run a REST::RequestFast instance. It delegates request interpolation to the registered request instance via the constructor. The default is a shim derived class of CGI.pm.

WWW::RESOURCE COMPATIBILITY:

If your derived class provides the WWW::Resource suggested callbacks browserprint() and ttl(), this method will honor those and fold in the new code hook mechanism.

WARNING:

If your derived class contains the method "browserprint()", the calling semantics for _all_ methods will be \%query.

    $instance->$method( \%query_hash );

If your derived class does NOT contain the method "browserprint()", it is assumed that you are using the new calling semantics where you method handler is passed the request instance.

    $instance->$method( $request_instance );

Thus ref( $arg ) will be "HASH" for the old style and an object reference for the new style.

handle_request()

USAGE:

    my( $restful ) = new REST::Resource( request_instance => new REST::Request() );
    $restful->handle_request();                         ## Implicit
    $restful->handle_request( new REST::Request() );    ## Explicit
    $restful->handle_request( new CGI() );              ## Explicit

DESCRIPTION:

This method runs a single action handler. Optionally pass in the CGI request to be handled.

method()

USAGE:

    my( $coderef ) = $restful->method( "GET" );         ## OR
    my( $method )  = $restful->method( "GET", \&get_handler, $description );

    $restful->$method( $request_interface_instance );

DESCRIPTION:

This accessor/mutator allows the caller to register or change the implementation behavior for a given HTTP method handler. The standard event handlers that are pre-registered are:

    GET
    PUT
    POST
    DELETE
    TRACE
    HEAD

Additionally, the following pseudo-methods provide over-ride control to derived class implementors.

    authenticate

Unless otherwise overridden, the default implementation for each of these methods is REST::Resource->unimplemented().

format()

USAGE:

    my( $format ) = $restful->format( "xml" );          ## OR
    $description   = $restful->format( "xml", \&format_xml, $description );

    $restful->$format( $request_interface_instance, $status, $data );

DESCRIPTION:

This accessor/mutator allows the caller to register or change the implementation behavior for a given output format.

description()

USAGE:

    my( $restful )      = new REST::Resource();
    my( $description )  = $restful->description( $name );

DESCRIPTION:

This accessor/mutator allows the caller to register or change the description for a given HTTP method handler or output format.

This is used by REST::Resource->api() to provide a description of the API.

PARAMETERS:

    $type       -- "methods" or "formats"
    $name       -- See the names appropriate for the given $type.
    $description-- The description to be set (or returned).

api()

USAGE:

    my( $status, $data ) = $this->api( $request_interface_instance );

DESCRIPTION:

This method generates a resultset that can be returned through $this->_return_result( $status, $data );

authenticate()

USAGE:

    my( $status, $data ) = $this->authenticate( $request_interface_instance );

DESCRIPTION:

This method may be overridden by a derived class that requires HTTP request authentication.

STATUS VALUES:

    RC_OK               (200)   -- Accept provided credentials, if any.
    RC_UNAUTHORIZED     (401)   -- Prompt user for credentials via dialog box.
    RC_FORBIDDEN        (403)   -- Reject provided credentials.

DERIVED IMPLEMENTATIONS:

This method may be overridden in the derived class in order to require a specific set of credentials.

format_xml()

USAGE:

    print $this->format_xml( $request_interface_instance, $status, $data );

DESCRIPTION:

This method will format $data as XML via XML::Dumper with an included in-document DTD. This method will only be registered if the module XML::Deumper is found in the execution environment.

format_text()

USAGE:

    print $this->format_text( $request_interface_instance, $status, $data );

DESCRIPTION:

Use Data::Dumper to emit $data in text/plain format.

format_html()

USAGE:

    print $this->format_html( $request_interface_instance, $status, $data );

DESCRIPTION:

Use Data::Dumper to emit $data, then translate it via simple <pre> tags with limited CSS to control the font-size.

format_json()

USAGE:

    print $this->format_json( $request_interface_instance, $status, $data );

DESCRIPTION:

This method will format $data in JSON (JavaScript Object Notation). This method will only be registered if JSON is found in the execution environment.

unimplemented()

USAGE:

    N/A

DESCRIPTION:

This method is invoked if an unregistered HTTP REQUEST_METHOD is invoked.

default_format()

USAGE:

    my( $format )       = $this->default_format( $request_interface_instance );
    print $this->$format( $status, $data );

DESCRIPTION:

This method will return the requested format. We look in two places. The first is in the query parameter list for the parameter "format". If that is defined, we return that value.

Otherwise, we scan through the list of q=1.0 Accept: headers and return the first matching MIME-type.

SAMPLE OPERA Accept: / User-Agent: HEADERS:

    Accept: text/html, application/xml;q=0.9, application/xhtml+xml,
            image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
    User-Agent: Opera/9.10 (X11; Linux i686; U; en)

SAMPLE FIREFOX Accept: / User-Agent: HEADERS:

    Accept: text/xml, application/xml, application/xhtml+xml, text/html;
            q=0.9, text/plain;
            q=0.8, image/png, */*;
            q=0.5
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3)
                Gecko/20070309 Firefox/2.0.0.3

SAMPLE MSIE Accept: / User-Agent: HEADERS:

    Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
            application/x-shockwave-flash, application/vnd.ms-powerpoint,
            application/vnd.ms-excel, application/msword, */*
    User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;
                             .NET CLR 1.1.4322; .NET CLR 2.0.50727)

SUGGESTIONS FOR JSON DEVELOPERS:

Use "Accept: text/javascript" or "?format=json" to get JSON output. The default algorithm will presume that the client is a human behind a browser and try to encourage html.

SUGGESTIONS FOR AJAX DEVELOPERS:

Use "Accept: application/xml" or "?format=xml" to get XML output. The default algorithm will presume that the client is a human behind a browser and try to encourage html.

get_request()

USAGE:

    my( $request )      = $restful->get_request();

DESCRIPTION:

Return a new request_interface instance. This instance must support the methods: new(), http(), param() and header().

SEE ALSO:

    REST::Request
    REST::RequestFast

_return_result() PRIVATE

USAGE:

    $this->_return_result( $request_interface_instance, $http_status, $data );

DESCRIPTION:

This method is handed output of a given REQUEST_METHOD handler and is responsible for appropriate status code emission and $data formatting.

SEE ALSO

    WWW::Resource
    http://www.peej.co.uk/articles/restfully-delicious.html
    http://www.xfront.com/REST-Web-Services.html
    http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm