4.4 RPC::XML


The last of the XML-RPC toolkits discussed here is the RPC::XML package, developed by one of the authors of this book, Randy J. Ray. This package isn't quite as independent as the XMLRPC::Lite implementation; it requires an external XML parser (currently the XML::Parser package from CPAN).

This package gives you a lot of flexibility in creating server applications. The main server class, RPC::XML::Server , can function as a standalone server using either the HTTP::Daemon class from the LWP package or the Net::Server package from CPAN. This latter package supports several different multiprocess models and provides all the background operation for whichever model the application chooses to use. Applications can even choose a model on-the-fly , rather than being locked into a specific one. The RPC::XML package also provides a server class designed especially to act as a content handler for Apache and mod_perl .

In addition to these choices in server management, the package comes with a set of server-side methods that implement the introspection interface pioneered by the PHP XML-RPC suite that was used in building the Meerkat API. This introspection interface was described in Chapter 3.

4.4.1 Client Example: meer2html.pl

The RPC::XML version of the Meerkat example isn't significantly different from the other toolkits' versions. Example 4-5 shows the relevant parts of this version of the script. Appendix C lists the full program.

Example 4-5. The meer2html-RPC::XML.pl script
 use RPC::XML::Client;     $client = RPC::XML::Client               # Remember that MEERKAT was declared with "use constant"               ->new(MEERKAT,                     error_handler =>                     sub { die "Transport error: $_[0]" });     sub show_data {     my $data = shift;         print STDOUT qq(<span class="meerkat">\n<dl>\n);     for (@$data) {         print STDOUT <<"END_HTML"; <dt class="title"><a href="$_->{link}">$_->{title}</a></dt> <dd class="description">$_->{description}</dd> END_HTML     }     print STDOUT qq(</dl>\n</span>\n); }     sub resolve_name {     my ($str, $name) = @_;         $name = "meerkat.get${name}BySubstring";     my $resp = $client->simple_request($name, $str);     die "resolve_name: $str returned more than 1 match"         if (@$resp > 1);         $resp->[0]{id}; }     sub get_data {     my ($key, $val, $num) = @_;         $client->simple_request('meerkat.getItems',                             { $key         => $val,                               time_period  => '7DAY',                               num_items    => $num,                               descriptions => 200 }); } 

As with the previous toolkits, only one library is used to get the functionality needed for a client. The constructor for the class is slightly different from both previous toolkits. The first argument must be the URL of the server the client will be conversing with. The constructor can accept some other arguments as well, but in this case, all that gets passed is the error_handler key followed by a closure that is used as a callback when errors occur.

The way RPC::XML handles errors is to return an error message as a simple string, whereas most methods return references normally. Setting the callback in this case causes an error to immediately call die , without the code having to check every return value later on.

For the sake of completeness, the show_data routine is also included here, despite being completely identical to the version used for RPC::XMLSimple and XMLRPC::Lite . This just underscores the simplicity of the way in which all three toolkits make data available to the programmer.

The resolve_name and get_data routines are slightly different than either of the two previous client examples. First, the method the RPC::XML::Client class uses is called simple_request . In fact, the client class defines two methods for making remote requests , the other one being send_request . The one used here returns native Perl data, while the other form returns a data object, similar to the behavior of XMLRPC::Lite . You can choose whether you wish to get the returned data as an object that can be tested for failure and treated as a fault or if you want to let callbacks handle that and just get the Perl data directly.

4.4.2 The RPC::XML::Client Class in Detail

Instances of the RPC::XML::Client class are containers for other class instances, specifically LWP::UserAgent and HTTP::Request . The user -agent object manages the actual communication to and from the server. The request object is created ahead of time so that common elements, such as the majority of the HTTP headers, can be precomputed, rather than newly evaluated on every outgoing message.

The RPC::XML::Client class has a number of methods available to application developers, some of which are summarized here. Appendix A contains a full reference to the classes for all the XML-RPC toolkits covered in this chapter.

new

This is the class constructor. It requires one initial argument, the URI of the server it will eventually connect to. In addition, these arguments are recognized:

error_handler

This key, followed by a subroutine reference, provides a callback routine to be invoked when an error occurs on the client side. It will be called with a single argument, the error message (usually the special Perl variable $@ ).

fault_handler

This is similar to the error callback but provides the callback when a fault is returned by the server (not to be confused with an actual server error or client-side error). When it is invoked, it is given a single argument: the RPC::XML::fault object containing the fault itself.

combined_handler

This is a convenience parameter for setting both handlers to the same callback at once.

Note that the callbacks don't get the client object in the argument list. See the callback-specific methods later for the alternative to specifying them at object creation.

send_request

This is the more robust of the two methods for calling remote procedures. The arguments it accepts may be either the remote name followed by zero or more data arguments, or a precomputed RPC::XML::request object (described later). The return value is either a data object reference or an error string. If the return value isn't a reference, it is a local (not server-side) error. Otherwise, server-side errors are returned as RPC::XML::fault objects.

simple_request

This method is functionally the same as send_request , with the difference that it returns native Perl data rather than a data-encapsulating object. This is meant to simplify smaller, shorter tasks . But it also means that the object can't be directly tested to see if it is a fault or not. The application must either use the callbacks or check that the return is a hash reference with only the keys faultCode and faultString . It is also difficult to discern an error message from the client code, unless the application was expecting a result that could not look like a text string. When using this method, the fault_handler and error_handler callbacks are strongly recommended.

uri

When called with no arguments, this method returns the current URI the client is connecting to. When an argument is passed, it is assumed to be a new URI and replaces the old one. This actually calls the uri method of the underlying HTTP::Request object. As such, it checks the validity of the URI, returning undef if it is invalid. It also means that an object of the URI class (the URI module is an installation dependency for LWP , so it will be available to the application) may be given as an argument.

error_handler , fault_handler , combined_handler

These methods get the current handler (when called with no arguments) or set a new handler (when called with an argument that is a code reference). The combined_handler method returns a two-element list because it is retrieving what may be two different callbacks.

These methods are useful for setting callbacks that need to have access to the object itself. They can be given closures as new callbacks that contain lexically scoped references to the object.

The RPC::XML::Client class doesn't auto-dispatch methods the way XMLRPC::Lite does. It does offer helper functions for creating data objects in cases where the Perl interpreter might not be able to correctly guess the type. Table 4-4 lists the data classes and the related helper functions.

Table 4-4. The RPC::XML data classes and functions

Data class

Helper

Description

 RPC::XML::int 
 RPC_INT 

The class holds an int value, though the helper function is rarely needed because Perl can identify an integer distinctly.

 RPC::XML::i4 
 RPC_I4 

Because an XML-RPC server that checks signatures considers int and i4 as distinct, this class and helper are useful for expressing this type rather than defaulting to int .

 RPC::XML:: Double 
 RPC_DOUBLE 

This class wraps a double value, which is also easily identified by Perl.

 RPC::XML:: String 
 RPC_STRING 

This class and helper function are useful for expressing string values that could be mistaken for other types.

 RPC::XML:: Boolean 
 RPC_BOOLEAN 

The boolean type can be created with any of true , false , yes , no , 1 , or . When serialized, it conforms to the XML-RPC specification.

 RPC::XML:: datetime_iso8601 
 RPC_DATETIME_ ISO8601 

This class wraps a date string but doesn't make any effort to validate the format.

 RPC::XML:: base64 
 RPC_BASE64 

The last of the classes (and helpers), this manages arbitrary chunks of data. The data is kept intact and only converted to Base64 for XML serialization.

All the helper functions take a single value as an argument and return an object reference from the appropriate class.

The classes themselves share a number of common methods:

new

This is the class constructor. It takes a new value and returns an object reference that wraps the data so that other parts of the module can use it directly. The RPC::XML::base64 constructor recognizes a second parameter to the constructor, used to signify that the data is already encoded as Base64.

as_string

Returns an XML fragment that expresses the object in a format that conforms to XML-RPC.

value

This method returns the underlying Perl value that the object wraps. Note that for the Base64 data, this returns the real data, not the encoded format.

type

Returns a simple identifier of the type for the object. Types are the names as defined in the XML-RPC specification ( int , dateTime.iso8601 , double , etc.).

is_fault

This is a boolean test to determine if the value object represents a fault. This is a constant false value in all the data classes, except for the RPC::XML::fault class, in which it is overridden to return true .

These methods apply to the RPC::XML::array and RPC::XML::struct classes, as well. Helper functions aren't available for them, but RPC::XML can map them from list and hash references, respectively.

Faults are managed in a class called RPC::XML::fault , which is a subclass of the struct class (and it doesn't have a helper function either). Faults must be created using the class constructor, but the constructor has a few shortcut approaches available to the writer:

new(RPC::XML::struct)

Creates the fault object from an existing RPC::XML::struct object.

new($int, $string)

Creates the object from an integer and string, which are explicitly converted and assigned to the correct structure keys.

new(faultCode => $code , faultString => $string)

In case the application chooses to be more explicit, this format is also supported. The two keys may be specified in either order.

As mentioned earlier, the fault class overrides the is_fault method to return true .

4.4.3 The Fortune Server Using RPC::XML::Server

As with previous implementations of the fortune example, the code in Example 4-6 is very simple. The RPC::XML::Server class version is longer than either of the previous two, however. This is because this server class doesn't provide a way to add local procedures by class or namespace as previous implementations do.

One thing that sets this server class apart from the previous two is that it manages and monitors the signatures associated with server-side routines. These are apparent in Example 4-6, and a client trying to connect to this server would have to form a valid request based on these specifications.

Example 4-6. The RPC::XML fortune server
 RPC::XML::Server->new(port => 9000)     ->add_proc({ name => 'books',                  signature => [ 'array',                                 'array string',                                 'array array' ],                  code => \&XRFortune::books })     ->add_proc({ name => 'fortune',                  signature => [ 'array',                                 'array string',                                 'array array' ],                  code => \&XRFortune::fortune })     ->add_proc({ name => 'weighted_fortune',                  signature => [ 'array',                                 'array string',                                 'array array' ],                  code => \&XRFortune::weighted_fortune })     ->server_loop; 

In this example, only the toolkit-specific lines are shown (the full code is given in Appendix C). The class constructor isn't that different in syntax or function from the previous examples. Like XMLRPC::Lite , most of the methods return the object reference upon success, allowing for methods to be chained together. Here, the add_proc method is called three times, adding one procedure each time. After the third call, the server_loop method handles the socket-accept logic until a signal of some kind causes it to exit, at which point the script also exits.

The design philosophy behind this server implementation is to exert more hands-on control over the methods and procedures that are published. It does this by allowing them to be added manually, loaded from a XML file (a format called "XPL," detailed later), or by loading entire directories of such files at a time. The XML file format will be discussed later, after we cover the basics of the server class itself.

4.4.4 The RPC::XML::Server Class in Detail

The RPC::XML::Server class is a container much like the server classes from RPC::XMLSimple and XMLRPC::Lite . Like those two, the basic functionality is found in the HTTP::Daemon class from the LWP package. But this server class can also use the Net::Server package from CPAN, if it is available. Net::Server provides a server framework with several different styles for the connection/service model. Besides the standard single-process and fork-per-request models, the package can also emulate Apache's preforking, multiple-child architecture. The package is worth evaluation independent of XML-RPC itself.

Server-side code is associated with a server object in one of three forms: a method, a procedure, or a function. The names distinguish the way the server interacts with the code when managing a request, as shown in Table 4-5.

Table 4-5. Types of server-side code

Style

Signatures

Server object

Procedure

Yes

No

Method

Yes

Yes

Function

No

No

A method ( RPC::XML::Method ) checks signatures but doesn't count the server object (which is passed as the first parameter when invoked) in the argument list. This allows the method itself to access the server object and its relevant data. A procedure ( RPC::XML::Procedure ) is almost the same as a method, but it doesn't get the server object. It does check signatures. Finally, the function ( RPC::XML::Function ) does no checking of signatures at all, and doesn't receive the server object. [2]

[2] As of Version 0.4 (the latest at the time of writing), there is no equivalent of RPC::XML::Function that includes the server object like a method does.

The constructor for the server class has a complex array of options available. These are summarized in Table 4-6. At present, much of the server functionality can be controlled only through these options. Not all have corresponding accessor methods for later modification.

Table 4-6. The options available to the RPC::XML::Server constructor

Option

Function

 no_http 

If this is passed with a non-false value, it prevents the constructor from allocating a HTTP::Daemon object. This is used by the Apache module or when the application wants to use Net::Server instead.

 no_default 

If passed and non-false, suppresses the loading of the interoperability methods provided by the package. These are detailed later.

 host port queue 

These four values may be used when the application wants to explicitly provide a hostname or address to bind to, port to bind to, or listen-queue size. They are used when creating the HTTP::Daemon object but may also be used with Net::Server , depending on other issues specific to that module.

 path 

By default, the daemon will not consider the path part of the URI used in the request. If this option is passed, the server handles requests only to the given path. This option has no meaning for the Apache module because it is configured to a specific location by Apache itself.

 xpl_path 

When adding methods or procedures by way of XPL files (covered later), this option allows you to specify additional directories to search for these files. Always takes a list reference as the argument.

 timeout 

The default time-out from the point when the server accepts a connection on the inbound socket until it expects to be able to read the full request is 10 seconds. This option can set a different value.

 auto_methods 

When this is passed and non-false, it allows the server to search for an unknown method by looking in the directories that can hold XPL files, for a file whose name matches the requested method. This is off by default, for obvious security reasons.

 auto_updates 

Like the previous option, this is off by default and applies only to code read from XPL files. If this is passed with a non-false value, then methods associated with an XPL file check the modification time of the file before being executed. If the file has been updated, it is reloaded before the request is dispatched.

Compared to the constructor, the remaining class methods are pretty simple and clear. Some of the more commonly used ones are:

add_method , add_proc

Adds a new method (or procedure) to the server. The new code may be specified as an object of the appropriate class, as a hash reference, or as a filename. If the value is a hash reference, the name of the method used ( add_method or add_proc ) determines the type of internal object used. Filenames are expected to be XPL files.

delete_method

Removes a method/procedure/function from the server by its published name. Returns the internal object that represents the method, in case the application wishes to re-add it later.

get_method

Gets the internal object for the method/procedure/function specified as an argument. The name requested must match the externally published name for the code.

add_methods_in_dir

Adds all the XPL files in the specified directory. Provided as a matter of convenience, for applications that collect their code as XPL files in one location.

share_methods , copy_methods

These methods allow two objects to share or copy method objects between them. Methods that are shared mean that each server has a reference to the same underlying object. Statistics gathered (such as call frequency) will be the same in both servers. Methods that are copied don't share any part except the code reference part within the internal object. This allows multiple server objects to use the same method code from XPL files without having to load them multiple times (which results in multiple anonymous subroutines from the same code block).

server_loop

This method is the center of server functionality for the objects. It is here that the server enters the socket-accept loop and waits for client connections. The application can pass arguments as a hash table (not a hash reference). If the object has no HTTP::Daemon instance associated with it ( no_http was specified at creation time), the hash table represents arguments that are passed to the run method of Net::Server . Otherwise, when using HTTP::Daemon , the only argument recognized is signal , whose value should be either a string specifying a signal by name or a list reference of more than one signal name. The signals specified are configured to act as interrupts for the accept loop.

As of Version 0.43 of the toolkit, RPC::XML::Server and the Apache subclass derived from it support compression using the Compress::Zlib module from CPAN, if available. The mechanics of expressing compression support in the message headers tries to be compatible with XMLRPC::Lite . In general, if the compression module is available and both ends of the conversation support compression, it should happen behind the scenes without any direct intervention on the part of the application.

4.4.4.1 Managing server-side code with XPL files

There have been numerous references to XPL files up to now. These files are a format originally created for expressing methods for the server. Since then, the syntax has been extended to distinguish methods, procedures, and functions. The actual code for the method may also be provided in multiple languages (though obviously only the Perl code matters to this server).

The goal of the format was to provide a way to exchange "bundles" of XML-RPC functionality with all the meta-data (signatures, help text, etc.) packaged as well. XPL originally referred to the file being a .pl wrapped in XML.

Example 4-7 shows a sample XPL file for one of the introspection routines the RPC::XML package includes. This example has the help text removed, as well as comment blocks, for brevity. The full example is listed in Appendix C.

Example 4-7. A sample XPL file, listMethods.xpl
 <?xml version="1.0"?> <!DOCTYPE methoddef SYSTEM "rpc-method.dtd"> <methoddef> <name>system.listMethods</name> <version>1.1</version> <signature>array</signature> <signature>array string</signature> <help> ... </help> <code language="perl"> <![CDATA[ #!/usr/bin/perl sub listMethods {     use strict;         my $srv = shift;     my $pat = shift;         my @list = sort $srv->list_methods;         # Exclude any that are hidden from introspection APIs     @list = grep(! $srv->get_method($_)->hidden, @list);     @list = grep(index($_, $pat) != -1, @list) if ($pat);         \@list; }     _ _END_ _ ]]></code> </methoddef> 

The layout of the file is very basic. The outer tag is one of methoddef , proceduredef , or functiondef . The container tag therefore declares the type of procedure being defined (in terms of the three types explained earlier). Within this container must be a name tag that provides the published name of the routine, at least one signature tag with a space-separated signature (except in the case of RPC::XML::Function declarations), and the code container with the actual Perl code for the routine.

The source code can be encoded one of two ways: using an XML CDATA section, as done earlier, or by ensuring that any < or & characters are entity-encoded. By using the CDATA approach and including both the #!perl start-up line and _ _END_ _ token at the end, the whole XPL file can be syntax-checked with perl -cx . (This doesn't validate the XML, it checks only the Perl syntax.)

In addition to the previous tags, the file can also define version (the version number/symbol of the code), hidden (an empty tag whose presence means the function should not be listed by the introspection API), and help (the minidocumentation text the introspection API uses when describing the routine to a client). These tags are all optional, and the version tag information isn't generally used anywhere except in the Apache status module, described later.

The application developer isn't left with the task of creating these files manually. The distribution of RPC::XML includes a utility script that can create the XPL files from files containing the Perl code and meta-data either in files or passed on the command line. The script, make_method , is documented and the distribution's Makefile.PL contains an example of integrating it into a build process. The distribution uses the XPL format to manage the introspection API routines that are provided. The make_method tool can build an XPL file from command-line data or from a meta-configuration file:

 make_method --name=reboot --helpfile=reboot.help --code=reboot.pl \             --signature=int --output=reboot.xpl     make_method --base=reboot 

4.4.5 The Introspection Interface for Servers

Table 4-7 lists the server introspection routines, along with their calling syntax (signatures) and basic functionality.

Table 4-7. The server introspection routines

Procedure name

Signature(s)

What it does

 system.identity 
 string 

Returns the server's identity in the form of a "name/version" string.

 system.introspection 
 array array array struct string 

Returns an array of structures that completely describe all the routines the server has configured (minus any that are tagged to be hidden). If a single name is specified, returns just the one structure. If an array is given, returns the structure for just those names.

 system.listMethods 
 array array string 

Lists the methods known to the server (minus hidden ones). If a string is passed, only the names that contain it as a substring are returned.

 system.methodHelp 
 string string array array 

Returns the help text for a single named method as a string or an array of help strings if passed an array of names.

 system.methodSignature 
 array string array array 

Returns the array of signatures for the named method or an array of arrays when more than one name is passed. Each signature is represented by an array of types, with the first being the type of return value to expect.

 system.multicall 
 array array 

Takes an array of structures, each representing one remote call. Makes the remote calls and returns an array of the result values.

 system.status 
 struct 

Returns a structure containing various runtime statistics and status reports from the server.

Both the primary server class and the Apache-specific class (described next ) default to loading these routines. Loading of the routines can be disabled by passing no_default => 1 in the constructor. Likewise, they can be added at a later time by calling a method on the server object called add_default_methods . The Apache server class has a slightly different version of system.status that reports additional information pertaining to the Apache environment.

4.4.6 Writing for Apache with Apache::RPC::Server

One distinct difference between the RPC::XML toolkit versus the others is the native support for running under Apache and mod_perl . The basic server class is subclassed in Apache::RPC::Server , which provides handlers for the PerlHandler and PerlChildInitHandler phases of the request/response lifecycle.

The handler and init_handler methods of the class are used as Apache location handlers, not as components of a script that would run under the Apache::Registry system. Instead, the Apache configuration maps a URI location (or more than one) to the XML-RPC subsystem. The objects of this class don't allocate HTTP listeners, operating instead on the request objects that Apache creates for handlers to access.

4.4.7 Configuring Server Objects

RPC server objects for the Apache environment are usually configured in a different manner than the other servers. In many cases, the configuration of the XML-RPC handler in Apache will be a simple PerlHandler directive:

 <Location /rpc>     SetHandler perl-script     PerlHandler Apache::RPC::Server </Location> 

This configuration doesn't install any server-side code except for the introspection routines. To give the administrator the ability to control the Apache RPC environment at this level, the Apache::RPC::Server class allows for most of the configurable parameters to be set using location-based directives. The following fragment shows many of these in use, with in-line comments explaining them:

 <Location /rpc>     SetHandler perl-script     # handler( ) doesn't have to be specified, but it can be     PerlHandler Apache::RPC::Server->handler     # define a name for the server, in case more than one     # will be configured for this Apache host     RpcServer rpc     # add a directory to the list of dirs that methods are     # kept in; may appear multiple times     RpcServerDir /opt/rpc/methods     # Add on specific method by file name; may also appear     # multiple times     RpcServerMethod /opt/rpc/extra/method.xpl     # suppress loading the introspection API methods     RpcDefMethods no     # disable auto-loading of methods...     RpcAutoMethods no     # ...but allow existing methods to auto-update:     RpcAutoUpdates yes </Location> 

There are more options detailed in the manpages for the class. When configured using Location directives, the server objects pick up their methods from a three-step sequence:

  1. Unless specifically disabled, the introspection methods are loaded first.

  2. Any RpcServerDir directives are treated, and all XPL files in each specified directory are loaded.

  3. Any RpcServerMethod directives are processed , and the files are loaded.

Any methods can be overridden in this process by a adding a new method under the name of an existing one. Thus, a server can add all the routines in a given directory, then use one or more RpcServerMethod directives to selectively replace some of them.

For more direct control over the RPC server objects, Apache can be configured using <Perl> sections in the configuration file. Using this method, the server-side code can be controlled in finer detail. The configuration also has full access to the server operations, and multiple server objects can be configured to share common methods, rather than having multiple copies of the same code in memory simultaneously . This fragment shows a sample configuration with two servers, one of which is access-controlled; the other isn't:

 <Perl>     # First, create and configure some Apache::RPC::Server # objects     # One regular one, with the standard settings: $main::defobj = Apache::RPC::Server->new(path => '/RPC',                                          auto_methods => 1,                                          auto_updates => 1); # One version without the default methods, and no # auto-actions $main::secobj = Apache::RPC::Server->new(no_default => 1,                                          path =>                                          '/rpc-secured'); # Give the secured one access to server.status, for report # gathering: $main::secobj->copy_methods($main::defobj, 'system.status');     # Imagine that add_method and/or add_methods_in_dir has been # used to add to the methods tables for those objects. Now # assign them to locations managed by Apache: $Location{'/RPC'} =     {         SetHandler  => 'perl-script',         PerlHandler => '$main::defobj'     }; $Location{'/rpc-secure'} =     {         SetHandler   => 'perl-script',         PerlHandler  => '$main::secobj',         AuthUserFile => '/etc/some_file',         AuthType     => 'Basic',         AuthName     => 'SecuredRPC',         'require'    => 'valid-user'     };     </Perl> 

In the example, the password-protected RPC server chose not to load the default methods. However, there was a need for the system.status method to track the statistics of the server. This can be explicitly added with add_method , but by using share_methods , the actual internal Perl code already present on the " open " server is used.

This approach has another advantage over the Location configuration method. When servers are configured using Perl sections, they are configured in the parent before the child processes are created. As a result, the children are created with the servers already in place and ready to operate . This is because the code sets the location handler to be an actual object reference, rather than a class name. When the handler is called for a request, it has the object there and ready, and doesn't have to first check for and retrieve a (possibly new) class instance to handle the request. With the Location configuration, the objects aren't created until the first request is received, which keeps them from being shared between children.

4.4.8 The Apache::RPC::Status Monitor

The last topic for this chapter isn't an XML-RPC processor, but it works together with the Apache server class. Apache::RPC::Status is a status monitor modeled after the Apache::Status package that reports the statistics of configured XML-RPC servers controlled by the Apache server.

The Apache::RPC::Status package lets a server administrator check the status of the RPC servers configured on a given host. As Figures Figure 4-1 through Figure 4-3 illustrate , the monitor allows the view to go from a high-level view of the server (or servers) down to the numbers for a given procedure.

Figure 4-1. The main monitor page
figs/pwsp_0401.gif
Figure 4-2. The server-level page, showing known methods
figs/pwsp_0402.gif
Figure 4-3. The method-level page, showing documentation
figs/pwsp_0403.gif

Fortunately, configuring and enabling the status monitor is much less intensive than are the RPC servers themselves:

 </Location /rpc-status>     SetHandler perl-script     PerlHandler Apache::RPC::Status </Location> 


Programming Web Services with Perl
Programming Web Services with Perl
ISBN: 0596002068
EAN: 2147483647
Year: 2000
Pages: 123

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net