File Coverage

lib/Catalyst/Plugin/Server/XMLRPC.pm
Criterion Covered Total %
statement 18 80 22.5
branch 0 30 0.0
condition 0 19 0.0
subroutine 6 11 54.5
pod n/a
total 24 140 17.1


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Catalyst::Plugin::Server::XMLRPC -- Catalyst XMLRPC Server Plugin
4              
5             =head1 SYNOPSIS
6              
7             package MyApp;
8             use Catalyst qw/Server Server::XMLRPC/;
9              
10             package MyApp::Controller::Example;
11             use base 'Catalyst::Controller';
12              
13             sub echo : XMLRPC { # available as: example.echo
14             my ( $self, $c, @args ) = @_;
15             $c->stash->{xmlrpc} = join ', ', @args;
16             }
17              
18             sub ping : XMLRPCPath('/ping') { # available as: ping
19             my ( $self, $c ) = @_;
20             $c->stash->{xmlrpc} = 'Pong';
21             }
22              
23             sub world : XMLRPCRegex(/hello/) { # available as: *hello*
24             my ($self, $c) = @_;
25             $c->stash->{xmlrpc} = 'World';
26             }
27              
28             sub echo : XMLRPCLocal { # available as: example.echo
29             my ( $self, $c, @args ) = @_;
30             $c->stash->{xmlrpc} = join ', ', @args;
31             }
32              
33             sub ping : XMLRPCGlobal { # available as: ping
34             my ( $self, $c ) = @_;
35             $c->stash->{xmlrpc} = 'Pong';
36             }
37              
38             =head1 DESCRIPTION
39              
40             XMLRPC Plugin for Catalyst which we tried to make compatible with the
41             way Catalyst works with URLS. Main features are:
42              
43             =over 4
44              
45             =item * Split XMLRPC methodNames by STRING to find out Controller.
46              
47             =item * Single entrypoint for XMLRPC calls, like http://host.tld/rpc
48              
49             =item * DispatchTypes (attributes) which work much the same as Catalyst attrs
50              
51             =item * XMLRPC Parameter handling transparent to Catalyst parameter handling
52              
53             =back
54              
55             =head1 HOW IT WORKS
56              
57             The default behaviour will handle XMLRPC Requests sent to C</rpc> by creating
58             an OBJECT containing XMLRPC specific parameters in C<< $c->req->xmlrpc >>.
59              
60             Directly after, it will find out the Path of the Action to dispatch to, by
61             splitting methodName by C<.>:
62              
63             methodName: hello.world
64             path : /hello/world
65              
66             From this point, it will dispatch to '/hello/world' when it exists,
67             like Catalyst Urls would do. What means: you will be able to set Regexes,
68             Paths etc on subroutines to define the endpoint.
69              
70             We discuss these custom XMLRPC attributes below.
71              
72             When the request is dispatched, we will return $c->stash->{xmlrpc} to the
73             xmlrpc client, or, when it is not available, it will return $c->stash to
74             the client. There is also a way of defining $c->stash keys to be send back
75             to the client.
76              
77             =head1 ATTRIBUTES
78              
79             You can mark any method in your Catalyst application as being
80             available remotely by using one of the following attributes,
81             which can be added to any existing attributes, except Private.
82             Remember that one of the mentioned attributes below are automatically
83             also Privates...
84              
85             =over 4
86              
87             =item XMLRPC
88              
89             Make this method accessible via XMLRPC, the same way as Local does
90             when using catalyst by URL.
91              
92             The following example will be accessible by method C<< hello.world >>:
93              
94             package Catalyst::Controller::Hello
95             sub world : XMLRPC {}
96              
97             =item XMLRPCLocal
98              
99             Identical version of attribute C<XMLRPC>
100              
101             =item XMLRPCGlobal
102              
103             Make this method accessible via XMLRPC, the same way as GLOBAL does
104             when using catalyst by URL.
105              
106             The following example will be accessible by method C<< ping >>:
107              
108             package Catalyst::Controller::Hello
109             sub ping : XMLRPCGlobal {}
110              
111             =item XMLRPCPath('/say/hello')
112              
113             Make this method accessible via XMLRPC, the same way as Path does
114             when using catalyst by URL.
115              
116             The following example will be accessible by method C<< say.hello >>:
117              
118             package Catalyst::Controller::Hello
119             sub hello : XMLRPCPath('/say/hello') {}
120              
121             =item XMLRPCRegex('foo')
122              
123             Make this method accessible via XMLRPC, the same way as Regex does
124             when using catalyst by URL.
125              
126             The following example will be accessible by example methods:
127             C<< a.foo.method >>
128             C<< wedoofoohere >>
129             C<< foo.getaround >>
130              
131             package Catalyst::Controller::Hello
132             sub hello : XMLRPCPath('foo') {}
133              
134             =back
135              
136             =head1 ACCESSORS
137              
138             Once you've used the plugin, you'll have an $c->request->xmlrpc accessor
139             which will return an C<Catalyst::Plugin::Server::XMLRPC> object.
140              
141             You can query this object as follows:
142              
143             =over 4
144              
145             =item $c->req->xmlrpc->is_xmlrpc_request
146              
147             Boolean indicating whether the current request has been initiated
148             via XMLRPC
149              
150             =item $c->req->xmlrpc->config
151              
152             Returns a C<Catalyst::Plugin::Server::XMLRPC::Config> object. See the
153             C<CONFIGURATION> below on how to use and configure it.
154              
155             =item $c->req->xmlrpc->body
156              
157             The body of the original XMLRPC call
158              
159             =item $c->req->xmlrpc->method
160              
161             The name of the original method called via XMLRPC
162              
163             =item $c->req->xmlrpc->args
164              
165             A list of parameters supplied by the XMLRPC call
166              
167             =item $c->req->xmlrpc->result_as_string
168              
169             The XML body that will be sent back to the XMLRPC client
170              
171             =item $c->req->xmlrpc->error
172              
173             Allows you to set xmlrpc fault code and message
174              
175             Example:
176              
177             $c->req->xmlrpc->error( [ 401 => 'Unauthorized' ] )
178              
179             To return status code C<401> with message C<Unauthorized>
180              
181             The default is to return error code C<500> on error.
182              
183             =back
184              
185             =head1 Server Accessors
186              
187             The following accessors are always available, whether you're in a xmlrpc
188             specific request or not
189              
190             =over 4
191              
192             =item $c->server->xmlrpc->list_methods
193              
194             Returns a HASHREF containing the available xmlrpc methods in Catalyst as
195             a key, and the C<Catalyst::Action> object as a value.
196              
197             =back
198              
199             =head1 CATALYST REQUEST
200              
201             To make things transparent, we try to put XMLRPC params into the Request
202             object of Catalyst. But first we will explain something about the XMLRPC
203             specifications.
204              
205             A full draft of these specifications can be found on:
206             C<http://www.xmlrpc.com/spec>
207              
208             In short, a xmlrpc-request consists of a methodName, like a subroutine
209             name, and a list of parameters. This list of parameters may contain strings
210             (STRING), arrays (LIST) and structs (HASH). Off course, these can be nested.
211              
212             =over 4
213              
214             =item $c->req->arguments
215              
216             We will put the list of arguments into $c->req->arguments, thisway you can
217             fetch this list within your dispatched-to-subroutine:
218              
219             sub echo : XMLRPC {
220             my ($self, $c, @args) = @_;
221             $c->log->debug($arg[0]); # Prints first XMLRPC parameter
222             # to debug log
223             }
224              
225             =item $c->req->parameters
226              
227             Because XMLRPC parameters are a LIST, we can't B<just> fill
228             $c->req->paremeters. To keep things transparent, we made an extra config
229             option what tells the XMLRPC server we can assume the following conditions
230             on all XMLRPC requests:
231             - There is only one XMLRPC parameter
232             - This XMLRPC parameter is a struct (HASH)
233              
234             We will put this STRUCT as key-value pairs into $c->req->parameters.
235              
236             =item $c->req->params
237              
238             Alias of $c->req->parameters
239              
240             =item $c->req->param
241              
242             Alias of $c->req->parameters
243              
244             =back
245              
246             =cut
247              
248             { package Catalyst::Plugin::Server::XMLRPC;
249              
250 1     1   61174 use strict;
  1         3  
  1         48  
251 1     1   7 use warnings;
  1         2  
  1         35  
252 1     1   1418 use attributes ();
  1         1689  
  1         24  
253 1     1   21675 use MRO::Compat;
  1         25917  
  1         34  
254 1     1   4743 use Data::Dumper;
  1         40562  
  1         1709  
255              
256             my $ServerClass = 'Catalyst::Plugin::Server::XMLRPC::Backend';
257              
258             ### only for development dumps!
259             my $Debug = 0;
260              
261             ###
262             ### Catalyst loading and dispatching
263             ###
264              
265             ### Loads our xmlrpc backend class in $c->server->xmlrpc
266             sub setup_engine {
267 0     0     my $class = shift;
268 0           $class->server->register_server(
269             'xmlrpc' => $ServerClass->new($class)
270             );
271 0           $class->next::method(@_);
272             }
273              
274             ### Will load our customized DispatchTypes into Catalyst
275             sub setup_dispatcher {
276 0     0     my $class = shift;
277              
278             ### Load custom DispatchTypes
279 0           $class->next::method( @_ );
280 0           $class->dispatcher->preload_dispatch_types(
281 0           @{$class->dispatcher->preload_dispatch_types},
282             qw/ +Catalyst::Plugin::Server::XMLRPC::DispatchType::XMLRPCPath
283             +Catalyst::Plugin::Server::XMLRPC::DispatchType::XMLRPCRegex/
284             );
285              
286 0           return $class;
287             }
288              
289             ### Loads the xmlrpc-server object, redispatch to the method
290             sub prepare_action {
291 0     0     my $c = shift;
292 0           my @args = @_;
293              
294             ### set up the accessor to hold an xmlrpc server instance
295 0           $c->req->register_server(
296             'xmlrpc' => Catalyst::Plugin::Server::XMLRPC::Request->new()
297             );
298              
299             ### are we an xmlrpc call? check the path against a regex
300 0           my $path = $c->server->xmlrpc->config->path;
301 0 0         if( $c->req->path =~ /$path/) {
302              
303 0           PREPARE: {
304             ### mark us as an xmlrpc request
305 0           $c->req->xmlrpc->is_xmlrpc_request(1);
306              
307 0 0         $c->log->debug( 'PREPARE WITH $c ' . Dumper ($c ) ) if $Debug;
308              
309 0 0         $c->req->xmlrpc->_deserialize_xml( $c ) or last PREPARE;
310              
311             ### CAVEAT: we consider backing up to a default for a
312             ### xml-rpc method when the method doesn't exist a security
313             ### risk. So when the exact method doesn't exist, we return
314             ### an error.
315             ### TODO ARGH Because of regex methods, this won't work
316              
317             ### set the new request path, the one we will forward to
318 0           $c->req->path( $c->req->xmlrpc->forward_path );
319              
320             ### filter change dispatch types to our OWN
321 0   0       { my $saved_dt = $c->dispatcher->dispatch_types || [];
  0            
322 0           my $dp_ns
323             = 'Catalyst::Plugin::Server::XMLRPC::DispatchType::';
324              
325 0 0         $c->dispatcher->dispatch_types(
326             [ grep {
327 0           $_->isa($dp_ns . 'XMLRPCPath')
328             or
329             $_->isa($dp_ns . 'XMLRPCRegex')
330             } @$saved_dt
331             ]
332             );
333              
334             ### run the rest of the prepare actions, we should have
335             ### an action object now
336 0           $c->next::method( @_ );
337              
338             ### restore the saved dispatchtypes
339 0           $c->dispatcher->dispatch_types( $saved_dt );
340             }
341              
342             ### check if we have a c->action now
343             ### check if the NEW action isn't hte same as the
344             ### OLD action -- which mean no method was found
345             ### Not needed, don't have an action until we NEXT
346 0 0 0       if( (not $c->action) &&
347             !$c->server->xmlrpc->private_methods->{
348             $c->req->xmlrpc->method
349             }
350             ) {
351 0           $c->req->xmlrpc->_error(
352             $c, qq[Invalid XMLRPC request: No such method]
353             );
354 0           last PREPARE;
355             }
356             }
357              
358             ### XMLRPC parameters and argument processing, see the Request
359             ### class below for information why we can't do it there.
360 0 0         $c->req->parameters( $c->req->xmlrpc->params )
361             if $c->server->xmlrpc->config->convert_params;
362              
363 0           $c->req->args($c->req->xmlrpc->args );
364              
365             ### we're no xmlrpc request, so just let others handle it
366             } else {
367 0           $c->next::method( @_ );
368             }
369             }
370              
371             ### before we dispatch, make sure no xmlrpc errors have happened already,
372             ### or an internal method has been called.
373             sub dispatch {
374 0     0     my $c = shift;
375              
376 0 0 0       if( $c->req->xmlrpc->is_xmlrpc_request and
  0 0 0        
377             scalar( @{ $c->error } )
378             ) {
379 0           1;
380             } elsif (
381             $c->req->xmlrpc->is_xmlrpc_request and
382             $c->server->xmlrpc->private_methods->{$c->req->xmlrpc->method}
383             ) {
384 0           $c->req->xmlrpc->run_method($c);
385             } else {
386 0           $c->next::method( @_ );
387             }
388             }
389              
390             sub finalize {
391 0     0     my $c = shift;
392              
393 0 0         if( $c->req->xmlrpc->is_xmlrpc_request ) {
394              
395             ### if we got an error anywhere, we'll return a fault
396             ### othwerise, the resultset will be returned
397             ### XXX TODO make error codes configurable ( done )
398             ### XXX TODO make messages customizable ( done )
399 0           my $res;
400 0           my $req_error = $c->req->xmlrpc->error;
401 0 0 0       if( scalar @{ $c->error } or $req_error ) {
  0            
402 0 0         if ($c->server->xmlrpc->config->show_errors) {
403 0 0 0       if ( $req_error && ref $req_error eq 'ARRAY' ) {
404 0           $res = RPC::XML::fault->new( @{ $req_error } );
  0            
405             } else {
406 0           $res = RPC::XML::fault->new( -1,
407 0           join $/, @{ $c->error }
408             );
409             }
410             } else {
411 0 0 0       if ( $req_error && ref $req_error eq 'ARRAY' ) {
412 0           $res = RPC::XML::fault->new( @{ $req_error } );
  0            
413             } else {
414 0           $c->log->debug("XMLRPC 500 Errors:\n" .
415 0           join("\n", @{ $c->error })
416             );
417 0           $res = RPC::XML::fault->new(
418             500,
419             'Internal Server Error'
420             );
421             }
422             }
423             } else {
424 0 0         if( exists $c->stash->{xmlrpc} ) {
425 0           $res = $c->stash->{xmlrpc};
426             } else {
427 0           $res = $c->stash;
428             }
429             }
430              
431 0           $c->res->body(
432             $c->req->xmlrpc->_serialize_xmlrpc( $c, $res )
433             );
434              
435             ### make sure to clear the error, so catalyst doesn't try
436             ### to deal with it
437 0           $c->error( 0 );
438             }
439              
440 0 0         $c->log->debug( 'FINALIZE ' . Dumper ( $c, \@_ ) ) if $Debug;
441              
442             ### always call finalize at the end, so Catalyst's final handler
443             ### gets called as well
444 0           $c->next::method( @_ );
445             }
446             }
447              
448             ### The server implementation
449             { package Catalyst::Plugin::Server::XMLRPC::Backend;
450              
451 1     1   10 use base qw/Class::Accessor::Fast/;
  1         3  
  1         1074  
452             use Data::Dumper;
453             use Scalar::Util 'reftype';
454              
455             __PACKAGE__->mk_accessors( qw/
456             dispatcher
457             private_methods
458             c
459             config
460             /
461             );
462              
463             sub new {
464             my $class = shift;
465             my $c = shift;
466             my $self = $class->next::method( @_ );
467              
468             $self->c($c);
469             $self->config( Catalyst::Plugin::Server::XMLRPC::Config->new( $c ) );
470             $self->private_methods({});
471             $self->dispatcher({});
472              
473             ### Internal function
474             $self->add_private_method(
475             'system.listMethods' => sub {
476             my ($c_ob, @args) = @_;
477             return [ keys %{
478             $c_ob->server->xmlrpc->list_methods;
479             } ];
480             }
481             );
482              
483             return $self;
484             }
485              
486             sub add_private_method {
487             my ($self, $name, $sub) = @_;
488              
489             return unless ($name && (reftype($sub) eq 'CODE'));
490             $self->private_methods->{$name} = $sub;
491             return 1;
492             }
493              
494             sub list_methods {
495             my ($self) = @_;
496             return $self->dispatcher->{Path}->methods($self->c);
497             }
498             }
499              
500             ### the config implementation ###
501             { package Catalyst::Plugin::Server::XMLRPC::Config;
502             use base 'Class::Accessor::Fast';
503              
504             ### XXX change me to an ENTRYPOINT!
505             my $DefaultPath = qr!^(/?)rpc(/|$)!i;
506             my $DefaultAttr = 'XMLRPC';
507             my $DefaultPrefix = '';
508             my $DefaultSep = '.';
509             my $DefaultShowErrors = 0;
510              
511             ### XXX add: stash_fields (to encode) stash_exclude_fields (grep -v)
512              
513             __PACKAGE__->mk_accessors(
514             qw/ path prefix separator attribute convert_params
515             show_errors xml_encoding
516             /
517             );
518              
519             ### return the cached version where possible
520             my $Obj;
521             sub new {
522             return $Obj if $Obj;
523              
524             my $class = shift;
525             my $c = shift;
526             my $self = $class->next::method;
527              
528             $self->prefix( $c->config->{xmlrpc}->{prefix} || $DefaultPrefix);
529             $self->separator($c->config->{xmlrpc}->{separator} || $DefaultSep);
530             $self->path( $c->config->{xmlrpc}->{path} || $DefaultPath);
531             $self->show_errors( $c->config->{xmlrpc}->{show_errors}
532             || $DefaultShowErrors );
533             $self->xml_encoding( $c->config->{xmlrpc}->{xml_encoding} )
534             if $c->config->{xmlrpc}->{xml_encoding};
535             $self->attribute($DefaultAttr);
536             $self->convert_params( 1 );
537              
538             ### cache it
539             return $Obj = $self;
540             }
541             }
542              
543             ### the server class implementation ###
544             { package Catalyst::Plugin::Server::XMLRPC::Request;
545              
546             use strict;
547             use warnings;
548              
549             use RPC::XML;
550             use RPC::XML::Parser;
551             use Scalar::Util 'reftype';
552             use Clone::Fast qw/clone/;
553              
554             use Data::Dumper;
555             use Text::SimpleTable;
556              
557             use base 'Class::Data::Inheritable';
558             use base 'Class::Accessor::Fast';
559              
560             __PACKAGE__->mk_accessors( qw[ forward_path args method body result
561             is_xmlrpc_request params
562             result_as_string internal_methods error
563             ] );
564              
565             __PACKAGE__->mk_classdata( qw[_xmlrpc_parser]);
566             __PACKAGE__->_xmlrpc_parser( RPC::XML::Parser->new );
567              
568             *parameters = *params;
569              
570             sub run_method {
571             my ($self, $c) = @_;
572              
573             $c->stash->{xmlrpc} =
574             &{$c->server->xmlrpc->private_methods->{$self->method}}($c, @{ $c->req->args });
575             }
576              
577             sub _deserialize_xml {
578             my ($self, $c) = @_;
579              
580             ### the parser will die on failure, make sure we catch it
581             my $content; my $req;
582             eval {
583             ## Make sure we do not read from empty filehandle,
584             ## by sending empty string
585             $content = do { local $/; my $b = $c->req->body; $b ? <$b> : ''};
586             $req = $self->_xmlrpc_parser->parse( $content );
587              
588             ### RPC::XML::Parser *returns* the error string on error
589             ### OR an object... *sigh*
590             die $req unless ref $req;
591              
592             ### Because we will die when request is not valid XMLRPC,
593             ### we simply test it. XXX TODO This results in a malformed
594             ### xml detected error, maybe we should catch it.
595             $req->name;
596             $req->args;
597             };
598              
599             ### parsing the request went fine
600             if ( not $@ and defined $req->name ) {
601              
602             $self->body( $content ); # original xml message
603             $self->method( $req->name ); # name of the method
604              
605             ### allow the args to be encoded as a HASH when requested
606             ### xmlrpc only knows a top level 'list', and we can not tell
607             ### if that is meant to be a hash or not
608             ### make sure to store args as an ARRAY REF! to be compatible
609             ### with catalyst
610             my @args = map { $_->value } @{ $req->args };
611             $self->args( \@args ); # parsed arguments
612              
613             ### HEURISTIC! IF @args == 1 AND it's a HASHREF,
614             ### then we can assume it's key => value pairs in there
615             ### and we will map them to $c->req->params
616             $self->params(
617             (@args == 1 && (reftype($args[0]) eq 'HASH'))
618             ? $args[0]
619             : {}
620             );
621             ### build the relevant namespace, action and path
622             { ### construct the forward path -- this allows catalyst to
623             ### do the hard work of dispatching for us
624             my $prefix = $c->server->xmlrpc->config->prefix;
625             my ($sep) = map { qr/$_/ }
626             map { quotemeta $_ }
627             $c->server->xmlrpc->config->separator;
628              
629             ### error checks here
630             if( $prefix =~ m|^/| ) {
631             $c->log->debug( __PACKAGE__ . ": Your prefix starts with".
632             " a / -- This is not recommended"
633             ) if $c->debug;
634             }
635              
636             unless( ref($sep) eq 'Regexp' ) {
637             $c->log->debug( __PACKAGE__ . ": Your separator is not a ".
638             "Regexp object -- This is not recommended"
639             ) if $c->debug;
640             }
641              
642             ### foo.bar => $prefix/foo/bar
643             ### DO NOT add a leading slash! uri.pm gets very upset
644             my @parts = split( $sep, $self->method );
645             my $fwd_path = join '/',
646             grep { defined && length } $prefix, @parts;
647              
648              
649             ### Complete our object-instance
650             $self->forward_path( $fwd_path );
651              
652             ### Notify system of called rpc method and arguments
653             $c->log->debug('XML-RPC: Method called: ' . $self->method)
654             if $c->debug;
655             if ($c->server->xmlrpc->config->convert_params &&
656             $self->params
657             ) {
658             my $params = Text::SimpleTable->new( [ 36, 'Key' ], [ 37, 'Value' ] );
659             foreach my $key (sort keys %{$self->params}) {
660             my $value = $self->params->{$key};
661             $value = ref($value) || $value;
662             $params->row($key, $value);
663             }
664             $c->log->debug("XML-RPC: Parameters:\n" . $params->draw)
665             if ($c->debug && %{$self->params});
666             }
667             }
668              
669             ### an error in parsing the request
670             } elsif ( $@ ) {
671             $self->_error( $c, qq[Invalid XMLRPC request "$@"] );
672             return;
673              
674             ### something is wrong, but who knows what...
675             } else {
676             $self->_error( $c, qq[Invalid XMLRPC request: Unknown error] );
677             return;
678             }
679              
680             return $self;
681             }
682              
683             ### alias arguments to args
684             *arguments = *args;
685              
686             ### Serializes the response to $c->res->body
687             sub _serialize_xmlrpc {
688             my ( $self, $c, $status ) = @_;
689              
690             local $RPC::XML::ENCODING = $c->server->xmlrpc->config->xml_encoding
691             if $c->server->xmlrpc->config->xml_encoding;
692            
693             local $Clone::Fast::BREAK_REFS = 1;
694              
695             my $res = RPC::XML::response->new(clone($status));
696             $c->res->content_type('text/xml');
697              
698             return $self->result_as_string( $res->as_string );
699             }
700              
701             ### record errors in the error and debug log -- just for convenience
702             sub _error {
703             my($self, $c, $msg) = @_;
704              
705             $c->log->debug( $msg ) if $c->debug;
706             $c->error( $msg );
707             }
708             }
709              
710              
711             1;
712              
713             __END__
714              
715             =head1 INTERNAL XMLRPC FUNCTIONS
716              
717             The following system functions are available to the public.,
718              
719             =over 4
720              
721             =item system.listMethods
722              
723             returns a list of available RPC methods.
724              
725             =back
726              
727             =head1 DEFINING RETURN VALUES
728              
729             The XML-RPC response must contain a single parameter, which may contain
730             an array (LIST), struct (HASH) or a string (STRING). To define the return
731             values in your subroutine, you can alter $c->stash in three different ways.
732              
733             =head2 Defining $c->stash->{xmlrpc}
734              
735             When defining $c->stash->{xmlrpc}, the XMLRPC server will return these values
736             to the client.
737              
738             =head2 When there is no $c->stash->{xmlrpc}
739              
740             When there is no C<< $c->stash->{xmlrpc} >> set, it will return the complete
741             C<< $c->stash >>
742              
743             =head1 CONFIGURATION
744              
745             The XMLRPC Plugin accepts the following configuration options, which can
746             be set in the standard Catalyst way (See C<perldoc Catalyst> for details):
747              
748             Your::App->config( xmlrpc => { key => value } );
749              
750             You can look up any of the config parameters this package uses at runtime
751             by calling:
752              
753             $c->server->xmlrpc->config->KEY
754              
755             =over 4
756              
757             =item path
758              
759             This specifies the entry point for your xmlrpc server; all requests are
760             dispatched from there. This is the url any XMLRCP client should post to.
761             You can change this to any C<Regex> wish.
762              
763             The default is: C<qr!^(/?)rpc(/|$)!i>, which matches on a top-level path
764             begining with C<rpc> preceeded or followed by an optional C</>, like this:
765              
766             http://your-host.tld/rpc
767              
768             =item prefix
769              
770             This specifies the prefix of the forward url.
771              
772             For example, with a prefix of C<rpc>, and a method C<foo>, the forward
773             path would be come C</rpc/foo>.
774              
775             The default is '' (empty).
776              
777             =item separator
778              
779             This is a STRING used to split your method on, allowing you to use
780             a hierarchy in your method calls.
781              
782             For example, with a separator of C<.> the method call C<demo.echo>
783             would be forwarded to C</demo/echo>. To make C<demo_echo> forward to the
784             same path, you would change the separator to C<_>,
785              
786             The default is C<.>, splitting methods on a single C<.>
787              
788             =item convert_params
789              
790             Make the arguments in C<< $c->req->xmlrpc->params >> available as
791             C<< $c->req->params >>.
792              
793             Defaults to true.
794              
795             =item show_errors
796              
797             Make system errors in C<< $c->error >> public to the rpc-caller in a XML-RPC
798             faultString. When show_errors is false, and your catalyst app generates a
799             fault, it will return an XML-RPC fault containing error number 500 and error
800             string: "Internal Server Error".
801              
802             Defaults to false.
803              
804             =item xml_encoding
805              
806             Change the xml encoding send over to the client. So you could change the
807             default encoding to C<UTF-8> for instance.
808              
809             Defaults to C<us-ascii> which is the default of C<RPC::XML>.
810              
811             =back
812              
813             =head1 DIAGNOSTICS
814              
815             =over 4
816              
817             =item Invalid XMLRPC request: No such method
818              
819             There is no corresponding method in your application that can be
820             forwarded to.
821              
822             =item Invalid XMLRPC request %s
823              
824             There was an error parsing the XMLRPC request
825              
826             =item Invalid XMLRPC request: Unknown error
827              
828             An unexpected error occurred
829              
830             =back
831              
832             =head1 TODO
833              
834             =over 4
835              
836             =item Make error messages configurable/filterable
837              
838             Right now, whatever ends up on $c->error gets returned to the client.
839             It would be nice to have a way to filter/massage these messages before
840             they are sent back to the client.
841              
842             =item Make stash filterable before returning
843              
844             Just like the error messages, it would be nice to be able to filter the
845             stash before returning so you can filter out keys you don't want to
846             return to the client, or just return a certain list of keys.
847             This all to make transparent use of XMLRPC and web easier.
848              
849             =back
850              
851             =head1 SEE ALSO
852              
853             L<Catalyst::Plugin::Server::XMLRPC::Tutorial>, L<Catalyst::Manual>,
854             L<Catalyst::Request>, L<Catalyst::Response>, L<RPC::XML>,
855             C<bin/rpc_client>
856              
857             =head1 ACKNOWLEDGEMENTS
858              
859             For the original implementation of this module:
860              
861             Marcus Ramberg, C<mramberg@cpan.org>
862             Christian Hansen
863             Yoshinori Sano
864              
865             =head1 AUTHORS
866              
867             Original Authors: Jos Boumans (kane@cpan.org) and Michiel Ootjers (michiel@cpan.org)
868              
869             Actually maintained by Jose Luis Martinez Torres JLMARTIN (jlmartinez@capside.com)
870              
871             =head1 THANKS
872              
873             Tomas Doran (BOBTFISH) for helping out with the debugging
874              
875             =head1 BUG REPORTS
876              
877             Please submit all bugs regarding C<Catalyst::Plugin::Server> to
878             C<bug-catalyst-plugin-server@rt.cpan.org>
879              
880             =head1 LICENSE
881              
882             This library is free software, you can redistribute it and/or modify
883             it under the same terms as Perl itself.
884              
885             =cut