Catalyst Advent - Day 20 - XMLRPC

Today we'll discover the wonderful world of web services. XMLRPC is unlike SOAP a very simple (and imo elegant) protocol, exchanging small XML messages like these.

Request:

    POST /api HTTP/1.1
    TE: deflate,gzip;q=0.3
    Connection: TE, close
    Accept: text/xml
    Accept: multipart/*
    Host: 127.0.0.1:3000
    User-Agent: SOAP::Lite/Perl/0.60
    Content-Length: 192
    Content-Type: text/xml

    <?xml version="1.0" encoding="UTF-8"?>
    <methodCall>
        <methodName>add</methodName>
        <params>
            <param><value><int>1</int></value></param>
            <param><value><int>2</int></value></param>
        </params>
    </methodCall>

Response:

    Connection: close
    Date: Tue, 20 Dec 2005 07:45:55 GMT
    Content-Length: 133
    Content-Type: text/xml
    Status: 200
    X-Catalyst: 5.62

    <?xml version="1.0" encoding="us-ascii"?>
    <methodResponse>
        <params>
            <param><value><int>3</int></value></param>
        </params>
    </methodResponse>

Sweet little protocol, isn't it? :)

Now follow these few steps to implement the application.

1. Install Catalyst (5.61 or later), Catalyst::Plugin::XMLRPC (0.06 or later) and SOAP::Lite (for XMLRPCsh.pl)

    % perl -MCPAN -e'install Catalyst'
    ...
    % perl -MCPAN -e'install Catalyst::Plugin::XMLRPC'
    ...

2. Create a myapp

    % catalyst.pl MyApp
    ...
    % cd MyApp

3. Add the XMLRPC plugin to MyApp.pm

    use Catalyst qw/-Debug Static::Simple XMLRPC/;

4. Add a api controller

    % ./script/myapp_create.pl controller API

5. Add a XMLRPC redispatch method and a add method with Remote attribute to lib/MyApp/Controller/API.pm

    sub default : Private {
        my ( $self, $c ) = @_;
        $c->xmlrpc;
    }

    sub add : Remote {
        my ( $self, $c, $a, $b ) = @_;
        return $a + $b;
    }

The default action is the entry point for each XMLRPC request, it will redispatch every request to methods with Remote attribute in the same class.

The add method is no traditional action, it has no private or public path. Only the XMLRPC dispatcher knows it exists.

6. Thats it! You have built your first web service, lets test it with XMLRPCsh.pl (part of SOAP::Lite)

    % ./script/myapp_server.pl
    ...
    % XMLRPCsh.pl http://127.0.0.1:3000/api
    Usage: method[(parameters)]
    > add( 1, 2 )
    --- XMLRPC RESULT ---
    '3'

Tip Of The Day

Your return data type is usually auto-detected, but you can easily enforce a specific one.

    sub add : Remote {
        my ( $self, $c, $a, $b ) = @_;
        return RPC::XML::int->new( $a + $b );
    }




Have fun!

--Sebastian