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