1###############################################################################
2#
3# This file copyright (c) 2001-2011 Randy J. Ray, all rights reserved
4#
5# Copying and distribution are permitted under the terms of the Artistic
6# License 2.0 (http://www.opensource.org/licenses/artistic-license-2.0.php) or
7# the GNU LGPL (http://www.opensource.org/licenses/lgpl-2.1.php).
8#
9###############################################################################
10#
11#   Description:    This package implements a RPC server as an Apache/mod_perl
12#                   content handler. It uses the RPC::XML::Server package to
13#                   handle request decoding and response encoding.
14#
15#   Functions:      handler
16#                   init_handler
17#                   new
18#                   get_server
19#                   version
20#                   INSTALL_DIR
21#                   list_servers
22#
23#   Libraries:      RPC::XML::Server
24#
25#   Global Consts:  $VERSION
26#
27###############################################################################
28
29package Apache::RPC::Server;
30
31use 5.008008;
32use strict;
33use warnings;
34use base qw(RPC::XML::Server);
35
36use Socket;
37use File::Spec;
38
39use Apache;
40use Apache::File; # For ease-of-use methods like set_last_modified
41use Apache::Constants ':common';
42
43use RPC::XML;
44
45## no critic (ProhibitSubroutinePrototypes)
46
47BEGIN
48{
49    $Apache::RPC::Server::INSTALL_DIR = (File::Spec->splitpath(__FILE__))[1];
50    %Apache::RPC::Server::SERVER_TABLE = ();
51}
52
53our $VERSION = '1.40';
54$VERSION = eval $VERSION; ## no critic (ProhibitStringyEval)
55
56sub version { return $Apache::RPC::Server::VERSION }
57
58sub INSTALL_DIR { return $Apache::RPC::Server::INSTALL_DIR }
59
60# Return a list (not list reference) of currently-known server objects,
61# represented as the text-keys from the hash table.
62sub list_servers { return keys %Apache::RPC::Server::SERVER_TABLE }
63
64# This is kinda funny, since I don't actually have a debug() method in the
65# RPC::XML::Server class at the moment...
66sub debug
67{
68    my ($self, $fmt, @args) = @_;
69
70    my $debug = ref($self) ? $self->SUPER::debug() : 1;
71
72    if ($fmt && $debug)
73    {
74        Apache::log_error(
75            sprintf "%p ($$): $fmt", (ref $self) ? $self : 0, @args
76        );
77    }
78
79    return $debug;
80}
81
82###############################################################################
83#
84#   Sub Name:       handler
85#
86#   Description:    This is the default routine that Apache will look for
87#                   when we set this class up as a content handler.
88#
89#   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
90#                   $class    in      scalar    Static name of the class we're
91#                                                 invoked in
92#                   $r        in      ref       Blessed Apache::Request object
93#
94#   Globals:        $DEF_OBJ
95#
96#   Returns:        Response code
97#
98###############################################################################
99sub handler ($$) ## no critic (ProhibitExcessComplexity)
100{
101    my $class = shift;
102    my $r = shift;
103
104    my ($srv, $content, $resp, $hdrs, $hdrs_out, $compress, $length,
105        $do_compress, $com_engine, $parser, $me, $resp_fh, $c, $peeraddr,
106        $peerhost, $peerport);
107
108    $srv = (ref $class) ? $class : $class->get_server($r);
109    $me = (ref($class) || $class) . '::handler';
110    if (! ref $srv)
111    {
112        $r->log_error("$me: PANIC! " . $srv);
113        return SERVER_ERROR;
114    }
115
116    # Set the relevant headers
117    $hdrs_out = $r->headers_out;
118    $hdrs = $srv->response->headers;
119    for (keys %{$hdrs}) { $hdrs_out->{$_} = $hdrs->{$_} }
120    $r->content_type('text/xml');
121    # We're essentially done if this was a HEAD request
122    if ($r->header_only)
123    {
124        # These headers are either only sent for HEAD requests or are different
125        # enough to move here from the above block
126        $r->set_last_modified($srv->started);
127        $r->send_http_header;
128    }
129    elsif ($r->method eq 'POST')
130    {
131        # Step 1: Do we have the correct content-type?
132        if ($r->header_in('Content-Type') !~ m{text/xml}i)
133        {
134            return DECLINED;
135        }
136        $compress = $srv->compress;
137        if ($compress and
138            ($r->header_in('Content-Encoding') || q{}) =~ $srv->compress_re)
139        {
140            $do_compress = 1;
141        }
142
143        # Step 2: Read the request in and convert it to a request object
144        # Note that this currently binds us to the Content-Length header a lot
145        # more tightly than I like. Expect to see this change sometime soon.
146        $length = $r->header_in('Content-Length');
147        $parser = $srv->parser->parse(); # Get the ExpatNB object
148        if ($do_compress)
149        {
150            # Spin up the compression engine
151            if (! ($com_engine = Compress::Zlib::inflateInit()))
152            {
153                $r->log_error("$me: Unable to init the Compress::Zlib engine");
154                return SERVER_ERROR;
155            }
156        }
157
158        while ($length)
159        {
160            $r->read($content, ($length < 2048) ? $length : 2048);
161            # If $content is undef, then the client has closed the connection
162            # on its end, and we're done (like it or not).
163            if (! defined $content)
164            {
165                $r->log_error("$me: Error reading request content");
166                return SERVER_ERROR;
167            }
168
169            $length -= length $content;
170            if ($do_compress)
171            {
172                if (! ($content = $com_engine->inflate($content)))
173                {
174                    $r->log_error("$me: Error inflating compressed data");
175                    return SERVER_ERROR;
176                }
177            }
178            if (! eval { $parser->parse_more($content); 1; })
179            {
180                if ($@)
181                {
182                    $r->log_error("$me: XML parse error: $@");
183                    return SERVER_ERROR;
184                }
185            }
186        }
187
188        if (! eval { $content = $parser->parse_done; 1; })
189        {
190            if ($@)
191            {
192                $r->log_error("$me: XML parse error at end: $@");
193                return SERVER_ERROR;
194            }
195        }
196
197        # Step 3: Process the request and encode the outgoing response
198        # Dispatch will always return a RPC::XML::response object
199        {
200            # We set some short-lifespan localized keys on $srv to let the
201            # methods have access to client connection info
202            $c = $r->connection;
203            ($peerport, $peeraddr) = unpack_sockaddr_in($c->remote_addr);
204            $peerhost = inet_ntoa($peeraddr);
205            # Set localized keys on $srv, based on the connection info
206            ## no critic (ProhibitLocalVars)
207            local $srv->{peeraddr} = $peeraddr;
208            local $srv->{peerhost} = $peerhost;
209            local $srv->{peerport} = $peerport;
210            $resp = $srv->dispatch($content);
211        }
212
213        # Step 4: Form up and send the headers and body of the response
214        $r->no_cache(1);
215        $do_compress = 0; # Clear it
216        if ($compress and ($resp->length > $srv->compress_thresh) and
217            (($r->header_in('Accept-Encoding') || q{}) =~ $srv->compress_re))
218        {
219            $do_compress = 1;
220            $hdrs_out->{'Content-Encoding'} = $compress;
221        }
222        # Determine if we need to spool this to a file due to size
223        if ($srv->message_file_thresh and
224            $srv->message_file_thresh < $resp->length)
225        {
226            if (! ($resp_fh = Apache::File->tmpfile))
227            {
228                $r->log_error("$me: Error opening tmpfile");
229                return SERVER_ERROR;
230            }
231
232            # Now that we have it, spool the response to it. This is a
233            # little hairy, since we still have to allow for compression.
234            # And though the response could theoretically be HUGE, in
235            # order to compress we have to write it to a second temp-file
236            # first, so that we can compress it into the primary handle.
237            if ($do_compress)
238            {
239                my $fh_compress = Apache::File->tmpfile;
240                if (! $fh_compress)
241                {
242                    $r->log_error("$me: Error opening second tmpfile");
243                    return SERVER_ERROR;
244                }
245
246                # Write the request to the second FH
247                $resp->serialize($fh_compress);
248                seek $fh_compress, 0, 0;
249
250                # Spin up the compression engine
251                if (! ($com_engine = Compress::Zlib::deflateInit()))
252                {
253                    $r->log_error("$me: Unable to initialize the " .
254                                  'Compress::Zlib engine');
255                    return SERVER_ERROR;
256                }
257
258                # Spool from the second FH through the compression engine,
259                # into the intended FH.
260                my $buf = q{};
261                my $out;
262                while (read $fh_compress, $buf, 4096)
263                {
264                    if (! (defined($out = $com_engine->deflate(\$buf))))
265                    {
266                        $r->log_error("$me: Compression failure in deflate()");
267                        return SERVER_ERROR;
268                    }
269                    print {$resp_fh} $out;
270                }
271                # Make sure we have all that's left
272                if  (! defined($out = $com_engine->flush))
273                {
274                    $r->log_error("$me: Compression flush failure in deflate");
275                    return SERVER_ERROR;
276                }
277                print {$resp_fh} $out;
278
279                # Close the secondary FH. Rewinding the primary is done
280                # later.
281                close $fh_compress; ## no critic (RequireCheckedClose)
282            }
283            else
284            {
285                $resp->serialize($resp_fh);
286            }
287            seek $resp_fh, 0, 0;
288
289            $r->set_content_length(-s $resp_fh);
290            $r->send_http_header;
291            $r->send_fd($resp_fh);
292        }
293        else
294        {
295            # Treat the content strictly in-memory
296            $content = $resp->as_string;
297            if ($do_compress)
298            {
299                $content = Compress::Zlib::compress($content);
300            }
301            $r->set_content_length(length $content);
302            $r->send_http_header;
303            $r->print($content);
304        }
305    }
306    else
307    {
308        # Flag this as an error, since we don't permit the other methods
309        return DECLINED;
310    }
311
312    return OK;
313}
314
315###############################################################################
316#
317#   Sub Name:       init_handler
318#
319#   Description:    Provide a handler for the PerlChildInitHandler phase that
320#                   walks through the table of server objects and updates the
321#                   child_started time on each.
322#
323#   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
324#                   $class    in      scalar    Calling class (this is a method
325#                                                 handler)
326#                   $r        in      ref       Apache reference object
327#
328#   Globals:        %SERVER_TABLE
329#
330#   Returns:        1
331#
332###############################################################################
333sub init_handler ($$)
334{
335    my ($class, $r) = @_;
336
337    for (values %Apache::RPC::Server::SERVER_TABLE)
338    {
339        $_->child_started(1);
340    }
341
342    return OK;
343}
344
345###############################################################################
346#
347#   Sub Name:       new
348#
349#   Description:    Create a new server object, which is blessed into this
350#                   class and thus inherits most of the important bits from
351#                   RPC::XML::Server.
352#
353#   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
354#                   $class    in      scalar    String or ref to ID the class
355#                   %argz     in      list      Type and relevance of args is
356#                                                 variable. See text.
357#
358#   Globals:        $INSTALL_DIR
359#
360#   Returns:        Success:    ref to new object
361#                   Failure:    error string
362#
363###############################################################################
364sub new ## no critic (ProhibitExcessComplexity)
365{
366    my ($class, %argz)  = @_;
367
368    my ($R, $servid, $prefix, $self, @dirs, @files, $ret, $no_def,
369        $do_auto, $do_mtime);
370
371    $R      = delete $argz{apache} || Apache->server;
372    $servid = delete $argz{server_id};
373    $prefix = delete $argz{prefix} || q{};
374    if (! $argz{path})
375    {
376        $argz{path} = $R->location;
377    }
378    if (! $servid)
379    {
380        $servid = substr $argz{path}, 1;
381    }
382
383    # For these Apache-conf type of settings, something explicitly passed in
384    # via %argz is allowed to override the config file. So after pulling the
385    # value, it is only applied if the corresponding key doesn't already exist
386
387    if (! exists $argz{debug})
388    {
389        # Is debugging requested?
390        $argz{debug} = $R->dir_config("${prefix}RpcDebugLevel") || 0;
391    }
392
393    # Check for disabling of auto-loading or mtime-checking
394    $do_auto  = $R->dir_config("${prefix}RpcAutoMethods") || 0;
395    $do_mtime = $R->dir_config("${prefix}RpcAutoUpdates") || 0;
396    foreach ($do_auto, $do_mtime) { $_ = /yes/i ? 1 : 0 }
397    if (! exists $argz{auto_methods})
398    {
399        $argz{auto_methods} = $do_auto;
400    }
401    if (! exists $argz{auto_updates})
402    {
403        $argz{auto_updates} = $do_mtime;
404    }
405
406    # If there is already an xpl_path, ensure that ours is on the top,
407    # otherwise add it.
408    if ($argz{xpl_path})
409    {
410        push @{$argz{xpl_path}}, $Apache::RPC::Server::INSTALL_DIR;
411    }
412    else
413    {
414        $argz{xpl_path} = [ $Apache::RPC::Server::INSTALL_DIR ];
415    }
416
417    # Create the object, ensuring that the defaults are not yet loaded:
418    my $raux = (ref($R) eq 'Apache') ? $R->server : $R;
419    $self = $class->SUPER::new(no_default => 1, no_http => 1,
420                               path => $argz{path},
421                               host => $raux->server_hostname || 'localhost',
422                               port => $raux->port,
423                               %argz);
424    # Non-ref means an error message
425    if (! ref $self)
426    {
427        return $self;
428    }
429    $self->started('set');
430
431    # Check to see if we should suppress the default methods.
432    # The default is "no" (don't suppress the default methods), so use || in
433    # the evaluation in case neither were set.
434    $no_def = $argz{no_default} ? 1 :
435        (($R->dir_config("${prefix}RpcDefMethods") || q{}) =~ /no/i) ? 1 : 0;
436    if (! $no_def)
437    {
438        $self->add_default_methods(-except => 'status.xpl');
439        # This should find the Apache version of system.status instead
440        $self->add_method('status.xpl');
441    }
442
443    # Determine what methods we are configuring for this server instance
444    @dirs  = split /:/, ($R->dir_config("${prefix}RpcMethodDir") || q{});
445    @files = split /:/, ($R->dir_config("${prefix}RpcMethod")    || q{});
446    # Load the directories first, then the individual files. This allows the
447    # files to potentially override entries in the directories.
448    for (@dirs)
449    {
450        $ret = $self->add_methods_in_dir($_);
451        if (! ref $ret)
452        {
453            return $ret;
454        }
455    }
456    for (@files)
457    {
458        $ret = $self->add_method($_);
459        if (! ref $ret)
460        {
461            return $ret;
462        }
463    }
464    if (@dirs)
465    {
466        # If there were any dirs specified for wholesale inclusion, add them
467        # to the search path for later reference.
468        $ret = $self->xpl_path;
469        unshift @{$ret}, @dirs;
470        $self->xpl_path($ret);
471    }
472
473    return $Apache::RPC::Server::SERVER_TABLE{$servid} = $self;
474}
475
476# Accessor similar to started() that has a time localized to this child process
477sub child_started
478{
479    my ($self, $set_started) = @_;
480
481    my $old = $self->{__child_started} || $self->started || 0;
482    if ($set_started)
483    {
484        $self->{__child_started} = time;
485    }
486
487    return $old;
488}
489
490###############################################################################
491#
492#   Sub Name:       get_server
493#
494#   Description:    Retrieve the server object appropriate for this Server
495#                   instance passed in right after $self. If the second arg is
496#                   not a reference, assume they are asking for an existing
497#                   server by name.
498#
499#   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
500#                   $self     in      sc/ref    Object ref or class name
501#                   $r        in      ref       Apache interface object ref
502#
503#   Globals:        %SERVER_TABLE
504#
505#   Returns:        object ref, either specific or the default object. Sends a
506#                   text string if new() fails
507#
508###############################################################################
509sub get_server
510{
511    my ($self, $r) = @_;
512
513    my ($prefix, $servid, $nocomp);
514
515    if (ref $r)
516    {
517        # Presume $r to in fact be an Apache reference, and use it as such.
518        # If the server that matches this is already in the table, return it.
519        # If it isn't, create it from the information we have available.
520        $prefix = $r->dir_config('RPCOptPrefix') || q{};
521        $servid = $r->dir_config("${prefix}RpcServer") || '<default>';
522        $nocomp = $r->dir_config('NoCompression') || q{};
523
524
525        return $Apache::RPC::Server::SERVER_TABLE{$servid} ||
526            $self->new(apache      => $r,
527                       server_id   => $servid,
528                       prefix      => $prefix,
529                       no_compress => $nocomp,
530                       path        => $r->location);
531    }
532    else
533    {
534        # If $r isn't a reference, then this is likely been called as a class
535        # method to get the server object for a specific name. Thus, if it
536        # doesn't exist yet, we lack sufficient information to create it on
537        # the fly.
538        return $Apache::RPC::Server::SERVER_TABLE{$r} ||
539            "Error: No such server object '$r' known (yet)";
540    }
541}
542
5431;
544
545__END__
546
547=pod
548
549=head1 NAME
550
551Apache::RPC::Server - A subclass of RPC::XML::Server tuned for mod_perl
552
553=head1 SYNOPSIS
554
555    # In httpd.conf:
556    PerlModule Apache::RPC::Server
557    PerlSetVar RpcMethodDir /var/www/rpc:/usr/lib/perl5/RPC-shared
558    PerlChildInitHandler Apache::RPC::Server->init_handler
559    ...
560    <Location /RPC>
561        SetHandler perl-script
562        PerlHandler Apache::RPC::Server
563    </Location>
564    </Location /RPC-limited>
565        SetHandler perl-script
566        PerlHandler Apache::RPC::Server
567        PerlSetVar RPCOptPrefix RpcLimit
568        PerlSetVar RpcLimitRpcServer Limited
569        PerlSetVar RpcLimitRpcMethodDir /usr/lib/perl5/RPC-shared
570    </Location>
571
572    # In the start-up Perl file:
573    use Apache::RPC::Server;
574
575=head1 DESCRIPTION
576
577The B<Apache::RPC::Server> module is a subclassing of B<RPC::XML::Server> that
578is tuned and designed for use within Apache with mod_perl.
579
580Provided are phase-handlers for the general request-processing phase
581(C<PerlHandler>) and the child-process initialization phase
582(C<PerlChildInitHandler>). The module should be loaded either by inclusion in a
583server start-up Perl script or by directives in the server configuration file
584(generally F<httpd.con>). One loaded, the configuration file may assign the
585module to handle one or more given locations with the general set of
586C<E<lt>LocationE<gt>> directives and familiar options. Additional configuration
587settings specific to this module are detailed below.
588
589Generally, externally-available methods are provided as files in the XML
590dialect explained in L<RPC::XML::Server|RPC::XML::Server>. A subclass derived
591from this class may of course use the methods provided by this class and its
592parent class for adding and manipulating the method table.
593
594=head1 SUBROUTINES/METHODS
595
596The methods that the server publishes are provided by a combination of the
597installation files and Apache configuration values. Details on remote method
598syntax and semantics is covered in L<RPC::XML::Server|RPC::XML::Server>.
599
600=head2 Methods
601
602In addition to inheriting all the methods from B<RPC::XML::Server>, the
603following methods are either added or overloaded by B<Apache::RPC::Server>:
604
605=over 4
606
607=item handler
608
609This is the default content-handler routine that B<mod_perl> expects when the
610module is defined as managing the specified location. This is provided as a
611I<method handler>, meaning that the first argument is either an object
612reference or a static string with the class name. This allows for other
613packages to easily subclass B<Apache::RPC::Server>.
614
615This routine takes care of examining the incoming request, choosing an
616appropriate server object to actually process the request, and returning the
617results of the remote method call to the client.
618
619=item init_handler
620
621This is another Apache-level handler, this one designed for installation as a
622C<PerlChildInitHandler>. At present, its only function is to iterate over all
623server object currently in the internal tables and invoke the C<child_started>
624method (detailed below) on each. Setting this handler assures that each child
625has a correct impression of when it started as opposed to the start time of the
626server itself.
627
628Note that this is only applied to those servers known to the master Apache
629process. In most cases, this will only be the default server object as
630described above. That is because of the delayed-loading nature of all servers
631beyond the default, which are likely only in child-specific memory. There are
632some configuration options described in the next section that can affect and
633alter this.
634
635=item new(HASH)
636
637This is the class constructor. It calls the superclass C<new> method, then
638performs some additional steps. These include installing the default methods
639(which includes an Apache-specific version of C<system.status>), adding the
640installation directory of this module to the method search path, and adding any
641directories or explicitly-requested methods to the server object.
642
643The arguments to the constructor are regarded as a hash table (not a hash
644reference), and are mostly passed unchanged to the constructor for
645B<RPC::XML::Server>. Three parameters are of concern to this class:
646
647=over 8
648
649=item apache
650
651The value associated with this key is a reference to an B<Apache> request
652object. If this is not passed, then it is assumed that this is being called in
653the start-up phase of the server and the value returned from
654C<< Apache->server >> (see L<Apache|Apache>) is used.
655
656=item server_id
657
658This provides the server ID string for the RPC server (not to be confused with
659the Apache server) that is being configured.
660
661=item prefix
662
663The prefix is used in retrieving certain configuration settings from the Apache
664configuration file.
665
666=back
667
668The server identification string and prefix concepts are explained in more
669detail in the next section. See L<RPC::XML::Server|RPC::XML::Server> for a full
670list of what additional arguments may be passed to B<new> for eventual proxy to
671the parent class constructor.
672
673=item child_started([BOOLEAN])
674
675This method is very similar to the C<started> method provided by
676B<RPC::XML::Server>. When called with no argument or an argument that evaluates
677to a false value, it returns the UNIX-style time value of when this child
678process was started. Due to the child-management model of Apache, this may very
679well be different from the value returned by C<started> itself. If given an
680argument that evaluates as true, the current system time is set as the new
681child-start time.
682
683If the server has not been configured to set this at child initialization, then
684the main C<started> value is returned. The name is different so that a child
685may specify both server-start and child-start times with clear distinction.
686
687=item get_server(APACHEREQ|STRING)
688
689Get the server object that corresponds to the argument passed. If the argument
690is a reference to an B<Apache> request object, use it to determine the name
691(by path, etc.) and return that object. If the parameter is not a reference,
692it is assumed to be the specific name desired.
693
694If the requested server object does not yet exist, an attempt will be made to
695create it and add it to the internal table. The newly-created object is then
696returned.
697
698=item list_servers
699
700Return a list of the I<names> used for all the current server instances. Does
701not return the server objects themselves (use B<get_server>, above, for that).
702
703=item version
704
705This method behaves exactly like the B<RPC::XML::Server> method, except that
706the version string returned is specific to this module instead.
707
708=item INSTALL_DIR
709
710As with B<version>, this is an overload of the parent-class static method that
711returns the installation directory of this particular module.
712
713=back
714
715=head2 Apache configuration semantics
716
717In addition to the known directives such as C<PerlHandler> and
718C<PerlChildInitHandler>, configuration of this system is controlled through a
719variety of settings that are manipulated with the C<PerlSetVar> and
720C<PerlAddVar> directives. These variables are:
721
722=over 4
723
724=item RPCOptPrefix [STRING]
725
726Sets a prefix string to be applied to all of the following names before trying
727to read their values. Useful for setting within a C<E<lt>LocationE<gt>> block
728to ensure that no settings from a higher point in the hierarchy influence the
729server being defined.
730
731=item RpcServer [STRING]
732
733Specify the name of the server to use for this location. If not passed, then
734the default server is used. This server may also be explicitly requested by the
735name "C<C<E<lt>defaultE<gt>>>". If more than one server is going to be created
736within the same Apache environment, this setting should always be used outside
737the default area so that the default server is not loaded down with extra
738method definitions. If a sub-location changes the default server, those changes
739will be felt by any location that uses that server.
740
741Different locations may share the same server by specifying the name with this
742variable. This is useful for managing varied access schemes, traffic analysis,
743etc.
744
745=item RpcMethodDir [DIRECTORY]
746
747This variable specifies directories to be scanned for method C<*.xpl>
748files. To specify more than one directory, separate them with "C<:>" just as
749with any other directory-path expression. All directories are kept (in the
750order specified) as the search path for future loading of methods.
751
752=item RpcMethod [FILENAME]
753
754This is akin to the directory-specification option above, but only provides a
755single method at a time. It may also have multiple values separated by
756colons. The method is loaded into the server table. If the name is not an
757absolute pathname, then it is searched for in the directories that currently
758comprise the path. The directories above, however, have not been added to the
759search path yet. This is because these directives are processed immediately
760after the directory specifications, and thus do not need to be searched. This
761directive is designed to allow selective overriding of methods in the
762previously-specified directories.
763
764=item RpcDefMethods [YES|NO]
765
766If specified and set to "no" (case-insensitive), suppresses the loading of the
767system default methods that are provided with this package. The absence of this
768setting is interpreted as a "yes", so explicitly specifying such is not needed.
769
770=item RpcAutoMethods [YES|NO]
771
772If specified and set to "yes", enables the automatic searching for a requested
773remote method that is unknown to the server object handling the request. If
774set to "no" (or not set at all), then a request for an unknown function causes
775the object instance to report an error. If the routine is still not found, the
776error is reported. Enabling this is a security risk, and should only be
777permitted by a server administrator with fully informed acknowledgement and
778consent.
779
780=item RpcAutoUpdates [YES|NO]
781
782If specified and set to "yes", enables the checking of the modification time
783of the file from which a method was originally loaded. If the file has
784changed, the method is re-loaded before execution is handed off. As with the
785auto-loading of methods, this represents a potential security risk, and should
786only be permitted by a server administrator with fully informed
787acknowledgement and consent.
788
789=back
790
791=head2 Specifying methods to the server(s)
792
793Methods are provided to an B<Apache::RPC::Server> object in three ways:
794
795=over 4
796
797=item Default methods
798
799Unless suppressed by a C<RpcDefMethods> option, the methods shipped with this
800package are loaded into the table. The B<Apache::RPC::Server> objects get a
801slightly different version of C<system.status> than the parent class does.
802
803=item Configured directories
804
805All method files (those ending in a suffix of C<*.xpl>) in the directories
806specified in the relevant C<RpcMethodDir> settings are read next. These
807directories are also (after the next step) added to the search path the object
808uses.
809
810=item By specific inclusion
811
812Any methods specified directly by use of C<RpcMethod> settings are loaded
813last. This allows for them to override methods that may have been loaded from
814the system defaults or the specified directories.
815
816=back
817
818If a request is made for an unknown method, the object will first attempt to
819find it by searching the path of directories that were given in the
820configuration as well as those that are part of the system (installation-level
821directories). If it is still not found, then an error is reported back to the
822requestor. By using this technique, it is possible to add methods to a running
823server without restarting it. It is a potential security hole, however, and it
824is for that reason that the previously-documented C<RpcAutoMethods> setting is
825provided.
826
827=head2 Usage Within <Perl> Sections
828
829To truly unlock the power of having the RPC server attached to a B<mod_perl>
830environment, the application and configuration of the server should be done
831within Perl-configuration blocks on the Apache server itself.
832
833In doing this, two immediate benefits are gained:
834
835=over 4
836
837=item (1)
838
839The rpc-server object gets created in the master Apache process, rather than
840within each child as a side-effect of the first request.  Especially in cases
841where there are going to be more than one server in use within the Apache
842environment, this boosts performance by allowing newly-created children to
843already have the server object and method table readily available.
844
845=item (2)
846
847It becomes possible to exert more detailed control over the creation and
848configuration of each server object. Combining the B<get_method> and
849B<add_method> operations permits "sharing" (of a sort) of methods between
850server objects. Recall from the B<RPC::XML::Server> documentation that, when a
851method is invoked, the first argument is the server object that is marshalling
852it.
853
854=back
855
856The following example illustrates these concepts in a fairly simple
857environment:
858
859    # In httpd.conf:
860    <Perl>
861
862    # First, create and configure some Apache::RPC::Server objects
863
864    # One regular one, with the standard settings:
865    $main::defobj = Apache::RPC::Server->new(path         => '/RPC',
866                                             auto_methods => 1,
867                                             auto_updates => 1);
868    # One version without the default methods, and no auto-actions
869    $main::secobj = Apache::RPC::Server->new(no_default => 1,
870                                             path => '/rpc-secured');
871
872    # Imagine that add_method and/or add_methods_in_dir has been used to
873    # add to the methods tables for those objects. Now assign them to
874    # locations managed by Apache:
875    $Location{'/RPC'} =
876        {
877            SetHandler  => 'perl-script',
878            PerlHandler => '$main::defobj'
879        };
880    $Location{'/rpc-secure'} =
881        {
882            SetHandler   => 'perl-script',
883            PerlHandler  => '$main::secobj',
884            AuthUserFile => '/etc/some_file',
885            AuthType     => 'Basic',
886            AuthName     => 'SecuredRPC',
887            'require'    => 'valid-user'
888        };
889
890    </Perl>
891
892Note that the assignment of the C<PerlHandler> value was a string
893representation of the object reference itself. B<mod_perl> performs a sort of
894"thaw" of this string when the location is accessed. Since this class
895implements itself as a I<method handler>, this causes the C<handler()> method
896for each of the locations to be handed the B<Apache::RPC::Server> object
897directly. Note also that the value assigned to C<PerlHandler> cannot be a
898lexical variable, or it will be out of scope when the handler is called.
899
900=head1 DIAGNOSTICS
901
902All methods return some type of reference on success, or an error string on
903failure. Non-reference return values should always be interpreted as errors
904unless otherwise noted.
905
906Where appropriate, the C<log_error> method from the B<Apache> package
907is called to note internal errors.
908
909=head1 CAVEATS
910
911This began as a reference implementation in which clarity of process and
912readability of the code took precedence over general efficiency. It is now
913being maintained as production code, but may still have parts that could be
914written more efficiently.
915
916=head1 BUGS
917
918Please report any bugs or feature requests to
919C<bug-rpc-xml at rt.cpan.org>, or through the web interface at
920L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=RPC-XML>. I will be
921notified, and then you'll automatically be notified of progress on
922your bug as I make changes.
923
924=head1 SUPPORT
925
926=over 4
927
928=item * RT: CPAN's request tracker
929
930L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=RPC-XML>
931
932=item * AnnoCPAN: Annotated CPAN documentation
933
934L<http://annocpan.org/dist/RPC-XML>
935
936=item * CPAN Ratings
937
938L<http://cpanratings.perl.org/d/RPC-XML>
939
940=item * Search CPAN
941
942L<http://search.cpan.org/dist/RPC-XML>
943
944=item * MetaCPAN
945
946L<https://metacpan.org/release/RPC-XML>
947
948=item * Source code on GitHub
949
950L<http://github.com/rjray/rpc-xml>
951
952=back
953
954=head1 LICENSE AND COPYRIGHT
955
956This file and the code within are copyright (c) 2011 by Randy J. Ray.
957
958Copying and distribution are permitted under the terms of the Artistic
959License 2.0 (L<http://www.opensource.org/licenses/artistic-license-2.0.php>) or
960the GNU LGPL 2.1 (L<http://www.opensource.org/licenses/lgpl-2.1.php>).
961
962=head1 CREDITS
963
964The B<XML-RPC> standard is Copyright (c) 1998-2001, UserLand Software, Inc.
965See <http://www.xmlrpc.com> for more information about the B<XML-RPC>
966specification.
967
968=head1 SEE ALSO
969
970L<RPC::XML::Server|RPC::XML::Server>, L<RPC::XML|RPC::XML>
971
972=head1 AUTHOR
973
974Randy J. Ray C<< <rjray@blackperl.com> >>
975
976=cut
977