Catalyst-Plugin-Server

 view release on metacpan or  search on metacpan

lib/Catalyst/Plugin/Server/XMLRPC.pm  view on Meta::CPAN

=head1 NAME

Catalyst::Plugin::Server::XMLRPC -- Catalyst XMLRPC Server Plugin

=head1 SYNOPSIS

    package MyApp;
    use Catalyst qw/Server Server::XMLRPC/;

    package MyApp::Controller::Example;
    use base 'Catalyst::Controller';

    sub echo : XMLRPC {                     # available as: example.echo
        my ( $self, $c, @args ) = @_;
        $c->stash->{xmlrpc} = join ', ', @args;
    }

    sub ping : XMLRPCPath('/ping') {        # available as: ping
        my ( $self, $c ) = @_;
        $c->stash->{xmlrpc} = 'Pong';
    }

    sub world : XMLRPCRegex(/hello/) {      # available as: *hello*
        my ($self, $c) = @_;
        $c->stash->{xmlrpc} = 'World';
    }

    sub echo : XMLRPCLocal {                # available as: example.echo
        my ( $self, $c, @args ) = @_;
        $c->stash->{xmlrpc} = join ', ', @args;
    }

    sub ping : XMLRPCGlobal {               # available as: ping
        my ( $self, $c ) = @_;
        $c->stash->{xmlrpc} = 'Pong';
    }

=head1 DESCRIPTION

XMLRPC Plugin for Catalyst which we tried to make compatible with the
way Catalyst works with URLS. Main features are:

=over 4

=item * Split XMLRPC methodNames by STRING to find out Controller.

=item * Single entrypoint for XMLRPC calls, like http://host.tld/rpc

=item * DispatchTypes (attributes) which work much the same as Catalyst attrs

=item * XMLRPC Parameter handling transparent to Catalyst parameter handling

=back

=head1 HOW IT WORKS

The default behaviour will handle XMLRPC Requests sent to C</rpc> by creating
an OBJECT containing XMLRPC specific parameters in C<< $c->req->xmlrpc >>.

Directly after, it will find out the Path of the Action to dispatch to, by
splitting methodName by C<.>:

  methodName: hello.world
  path      : /hello/world

From this point, it will dispatch to '/hello/world' when it exists,
like Catalyst Urls would do. What means: you will be able to set Regexes,
Paths etc on subroutines to define the endpoint.

We discuss these custom XMLRPC attributes below.

When the request is dispatched, we will return $c->stash->{xmlrpc} to the
xmlrpc client, or, when it is not available, it will return $c->stash to
the client. There is also a way of defining $c->stash keys to be send back
to the client.

=head1 ATTRIBUTES

You can mark any method in your Catalyst application as being
available remotely by using one of the following attributes,
which can be added to any existing attributes, except Private.
Remember that one of the mentioned attributes below are automatically
also Privates...

=over 4

=item XMLRPC

Make this method accessible via XMLRPC, the same way as Local does
when using catalyst by URL.

The following example will be accessible by method C<< hello.world >>:

  package Catalyst::Controller::Hello
  sub world : XMLRPC {}

=item XMLRPCLocal

Identical version of attribute C<XMLRPC>

=item XMLRPCGlobal

Make this method accessible via XMLRPC, the same way as GLOBAL does
when using catalyst by URL.

The following example will be accessible by method C<< ping >>:

  package Catalyst::Controller::Hello
  sub ping : XMLRPCGlobal {}

=item XMLRPCPath('/say/hello')

lib/Catalyst/Plugin/Server/XMLRPC.pm  view on Meta::CPAN

You can query this object as follows:

=over 4

=item $c->req->xmlrpc->is_xmlrpc_request

Boolean indicating whether the current request has been initiated
via XMLRPC

=item $c->req->xmlrpc->config

Returns a C<Catalyst::Plugin::Server::XMLRPC::Config> object. See the 
C<CONFIGURATION> below on how to use and configure it.

=item $c->req->xmlrpc->body

The body of the original XMLRPC call

=item $c->req->xmlrpc->method

The name of the original method called via XMLRPC

=item $c->req->xmlrpc->args

A list of parameters supplied by the XMLRPC call

=item $c->req->xmlrpc->result_as_string

The XML body that will be sent back to the XMLRPC client

=item $c->req->xmlrpc->error

Allows you to set xmlrpc fault code and message

Example:

  $c->req->xmlrpc->error( [ 401 => 'Unauthorized' ] )

To return status code C<401> with message C<Unauthorized>

The default is to return error code C<500> on error.

=back

=head1 Server Accessors

The following accessors are always available, whether you're in a xmlrpc
specific request or not

=over 4

=item $c->server->xmlrpc->list_methods

Returns a HASHREF containing the available xmlrpc methods in Catalyst as
a key, and the C<Catalyst::Action> object as a value.

=back

=head1 CATALYST REQUEST

To make things transparent, we try to put XMLRPC params into the Request
object of Catalyst. But first we will explain something about the XMLRPC
specifications.

A full draft of these specifications can be found on:
C<http://www.xmlrpc.com/spec>

In short, a xmlrpc-request consists of a methodName, like a subroutine
name, and a list of parameters. This list of parameters may contain strings
(STRING), arrays (LIST) and structs (HASH). Off course, these can be nested.

=over 4

=item $c->req->arguments

We will put the list of arguments into $c->req->arguments, thisway you can
fetch this list within your dispatched-to-subroutine:

  sub echo : XMLRPC {
      my ($self, $c, @args) = @_;
      $c->log->debug($arg[0]);              # Prints first XMLRPC parameter
                                            # to debug log
  }

=item $c->req->parameters

Because XMLRPC parameters are a LIST, we can't B<just> fill
$c->req->paremeters. To keep things transparent, we made an extra config
option what tells the XMLRPC server we can assume the following conditions
on all XMLRPC requests:
- There is only one XMLRPC parameter
- This XMLRPC parameter is a struct (HASH)

We will put this STRUCT as key-value pairs into $c->req->parameters.

=item $c->req->params

Alias of $c->req->parameters

=item $c->req->param

Alias of $c->req->parameters

=back

=cut

{   package Catalyst::Plugin::Server::XMLRPC;

    use strict;
    use warnings;
    use attributes ();
    use MRO::Compat;
    use Data::Dumper;

    my $ServerClass = 'Catalyst::Plugin::Server::XMLRPC::Backend';

    ### only for development dumps!
    my $Debug = 0;

    ###
    ### Catalyst loading and dispatching
    ###

    ### Loads our xmlrpc backend class in $c->server->xmlrpc
    sub setup_engine {
        my $class = shift;
        $class->server->register_server(
                    'xmlrpc' => $ServerClass->new($class)
                );
        $class->next::method(@_);
    }

    ### Will load our customized DispatchTypes into Catalyst
    sub setup_dispatcher {
        my $class = shift;

        ### Load custom DispatchTypes
        $class->next::method( @_ );
        $class->dispatcher->preload_dispatch_types(
            @{$class->dispatcher->preload_dispatch_types},
            qw/ +Catalyst::Plugin::Server::XMLRPC::DispatchType::XMLRPCPath
                +Catalyst::Plugin::Server::XMLRPC::DispatchType::XMLRPCRegex/
        );

        return $class;
    }

lib/Catalyst/Plugin/Server/XMLRPC.pm  view on Meta::CPAN


=item convert_params

Make the arguments in C<< $c->req->xmlrpc->params >> available as
C<< $c->req->params >>. 

Defaults to true.

=item show_errors

Make system errors in C<< $c->error >> public to the rpc-caller in a XML-RPC
faultString. When show_errors is false, and your catalyst app generates a
fault, it will return an XML-RPC fault containing error number 500 and error
string: "Internal Server Error".

Defaults to false.

=item xml_encoding

Change the xml encoding send over to the client. So you could change the
default encoding to C<UTF-8> for instance.

Defaults to C<us-ascii> which is the default of C<RPC::XML>.

=back

=head1 DIAGNOSTICS

=over 4

=item Invalid XMLRPC request: No such method

There is no corresponding method in your application that can be
forwarded to.

=item Invalid XMLRPC request %s

There was an error parsing the XMLRPC request

=item Invalid XMLRPC request: Unknown error

An unexpected error occurred

=back

=head1 TODO

=over 4

=item Make error messages configurable/filterable

Right now, whatever ends up on $c->error gets returned to the client.
It would be nice to have a way to filter/massage these messages before
they are sent back to the client.

=item Make stash filterable before returning

Just like the error messages, it would be nice to be able to filter the
stash before returning so you can filter out keys you don't want to 
return to the client, or just return a certain list of keys. 
This all to make transparent use of XMLRPC and web easier.

=back

=head1 SEE ALSO

L<Catalyst::Plugin::Server::XMLRPC::Tutorial>, L<Catalyst::Manual>, 
L<Catalyst::Request>, L<Catalyst::Response>,  L<RPC::XML>, 
C<bin/rpc_client>

=head1 ACKNOWLEDGEMENTS

For the original implementation of this module:

Marcus Ramberg, C<mramberg@cpan.org>
Christian Hansen
Yoshinori Sano

=head1 AUTHORS

Original Authors: Jos Boumans (kane@cpan.org) and Michiel Ootjers (michiel@cpan.org)

Actually maintained by Jose Luis Martinez Torres JLMARTIN (jlmartinez@capside.com)

=head1 THANKS

Tomas Doran (BOBTFISH) for helping out with the debugging

=head1 BUG REPORTS

Please submit all bugs regarding C<Catalyst::Plugin::Server> to
C<bug-catalyst-plugin-server@rt.cpan.org>

=head1 LICENSE

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut



( run in 1.274 second using v1.01-cache-2.11-cpan-39bf76dae61 )