You want to write a server for an XML-RPC web service.
Use the SOAP-Lite distribution from CPAN, which supports XML-RPC. Your server can be either standalone:
use XMLRPC::Transport::HTTP; $daemon = XMLRPC::Transport::HTTP::Daemon ->new(LocalPort => $PORT) ->dispatch_to('ClassName') ->handle( );
or a CGI script:
use XMLRPC::Transport::HTTP; $daemon = XMLRPC::Transport::HTTP::CGI ->dispatch_to('ClassName') ->handle( );
In both cases, incoming methods will be invoked on the class named in the dispatch_to method (it will be required if it is not already loaded):
package ClassName; sub handler { my ($class, $arg_hash_ref) = @_; # ... }
The SOAP-Lite toolkit's modules take care of translating between Perl's native data structures and the XML representation of those values. However, it's up to you how the server decides which method to invoke when a request arrives. This process of matching an XML-RPC request to a Perl function is known as dispatching.
It looks strange to see all those chained method invocation in the Solution. When used to set a value, XMLRPC::Lite methods return their invocation, which lets you chain methods rather than repeat $daemon over and over again:
$daemon = XMLRPC::Transport::HTTP::Daemon; $daemon->new(LocalPort => $PORT); $daemon->dispatch_to('ClassName'); $daemon->handle( );
The new constructor takes IO::Socket::INET's constructor parameters as well, so you can say ReuseAddr => 1, for example.
When you give the dispatch_to method a class name argument (as in the Solution), the XML-RPC server looks for methods in that class. If the server in the Solution receives a request for the ClassName.hasBeen method (XML-RPC methods are typically in IntraCaps), it invokes the ClassName->hasBeen method for a response.
Give dispatch_to a method name or list of method names, optionally qualified with a package name. This tells Perl that only those methods should be invoked. For example, the following code ensures that only the hasBeen and willBe methods from the main package and the canDo method from the MonkeySea class are valid:
$daemon->dispatch_to('hasBeen', 'willBe', 'MonkeySea::canDo')
Finally, give dispatch_to a pathname (optionally, as with method names or class names), and XMLRPC::Lite will load modules as needed from that directory at runtime:
$daemon->dispatch_to('/path/to/exposed/modules', 'MyClass::API');
This means "all modules in /path/to/exposed/modules and MyClass::API can be called through XML-RPC." MyClass::API might have been preloaded, or it might be found in @INC. This specifically does not mean "only dispatch to the MyClass::API in /path/to/exposed/modules."
Recipe 18.12; Recipe 18.13