=head1 NAME

XML::RPC::Fast - Fast and modular implementation for an XML-RPC client and server


=cut

=head1 SYNOPSIS

Generic usage

    use XML::RPC::Fast;
    
    my $server = XML::RPC::Fast->new( undef, %args );
    my $client = XML::RPC::Fast->new( $uri,  %args );

Create a simple XML-RPC service:

    use XML::RPC::Fast;
    
    my $rpc = XML::RPC::Fast->new(
        undef,                         # the url is not required by server
        external_encoding => 'koi8-r', # any encoding, accepted by Encode
        #internal_encoding => 'koi8-r', # not supported for now
    );
    my $xml = do { local $/; <STDIN> };
    length($xml) == $ENV{CONTENT_LENGTH} or warn "Content-Length differs from actually received";
    
    print "Content-type: text/xml; charset=$rpc->{external_encoding}\n\n";
    print $rpc->receive( $xml, sub {
        my ( $methodname, @params ) = @_;
        return { you_called => $methodname, with_params => \@params };
    } );

Make a call to an XML-RPC service:

    use XML::RPC::Fast;
    
    my $rpc = XML::RPC::Fast->new(
        'http://your.hostname/rpc/url'
    );
    
    # Syncronous call
    my @result = $rpc->req(
        call => [ 'examples.getStateStruct', { state1 => 12, state2 => 28 } ],
        url => 'http://...',
    );
    
    # Syncronous call (compatibility method)
    my @result = $rpc->call( 'examples.getStateStruct', { state1 => 12, state2 => 28 } );
    
    # Syncronous or asyncronous call
    $rpc->req(
        call => ['examples.getStateStruct', { state1 => 12, state2 => 28 }],
        cb   => sub {
            my @result = @_;
        },
    );
    
    # Syncronous or asyncronous call (compatibility method)
    $rpc->call( sub {
        my @result = @_;
        
    }, 'examples.getStateStruct', { state1 => 12, state2 => 28 } );
    

=head1 DESCRIPTION

XML::RPC::Fast is format-compatible with XML::RPC, but may use different encoders to parse/compose xml.
Curerntly included encoder uses L<XML::LibXML>, and is 3 times faster than XML::RPC and 75% faster, than XML::Parser implementation

=head1 METHODS

=head2 new ($url, %args)

Create XML::RPC::Fast object, server if url is undef, client if url is defined

=head2 req( %ARGS )

Clientside. Make syncronous or asyncronous call (depends on UA).

If have cb, will invoke $cb with results and should not croak

If have no cb, will return results and croak on error (only syncronous UA)

Arguments are

=over 4

=item call => [ methodName => @args ]

array ref of call arguments. Required

=item cb => $cb->(@results)

Invocation callback. Optional for syncronous UA. Behaviour is same as in call with C<$cb> and without

=item url => $request_url

Alternative invocation URL. Optional. By default will be used defined from constructor

=item headers => { http-headers hashref }

Additional http headers to request

=item external_encoding => '...,

Specify the encoding, used inside XML container just for this request. Passed to encoder

=back

=head2 call( 'method_name', @arguments ) : @results

Clientside. Make syncronous call and return results. Croaks on error. Just a simple wrapper around C<req>

=head2 call( $cb->(@res), 'method_name', @arguments ): void

Clientside. Make syncronous or asyncronous call (depends on UA) and invoke $cb with results. Should not croak. Just a simple wrapper around C<req>

=head2 receive ( $xml, $handler->($methodName,@args) ) : xml byte-stream

Serverside. Process received XML and invoke $handler with parameters $methodName and @args and returns response XML

On error conditions C<$handler> could set C<$XML::RPC::Fast::faultCode> and die, or return C<rpcfault($faultCode,$faultString)>

    ->receive( $xml, sub {
        # ...
        return rpcfault( 3, "Some error" ) if $error_condition
        $XML::RPC::Fast::faultCode = 4 and die "Another error" if $another_error_condition;

        return { call => $methodname, params => \@params };
    })

=head2 registerType

Proxy-method to encoder. See L<XML::RPC::Enc>

=head2 registerClass

Proxy-method to encoder. See L<XML::RPC::Enc>

=head1 OPTIONS

Below is the options, accepted by new()

=head2 ua

Client only. Useragent object, or package name

    ->new( $url, ua => 'LWP' ) # same as XML::RPC::UA::LWP
    # or 
    ->new( $url, ua => 'XML::RPC::UA::LWP' )
    # or 
    ->new( $url, ua => XML::RPC::UA::LWP->new( ... ) )
    # or 
    ->new( $url, ua => XML::RPC::UA::Curl->new( ... ) )

=head2 timeout

Client only. Timeout for calls. Passed directly to UA

    ->new( $url, ua => 'LWP', timeout => 10 )

=head2 useragent

Client only. Useragent string. Passed directly to UA

    ->new( $url, ua => 'LWP', useragent => 'YourClient/1.11' )

=head2 encoder

Client and server. Encoder object or package name

    ->new( $url, encoder => 'LibXML' )
    # or 
    ->new( $url, encoder => 'XML::RPC::Enc::LibXML' )
    # or 
    ->new( $url, encoder => XML::RPC::Enc::LibXML->new( ... ) )

=head2 internal_encoding B<NOT IMPLEMENTED YET>

Specify the encoding you are using in your code. By default option is undef, which means flagged utf-8
For translations is used Encode, so the list of accepted encodings fully derived from it.

=head2 external_encoding

Specify the encoding, used inside XML container. By default it's utf-8. Passed directly to encoder

    ->new( $url, encoder => 'LibXML', external_encoding => 'koi8-r' )

=head1 ACCESSORS

=head2 url

Get or set client url

=head2 encoder

Direct access to encoder object

=head2 ua

Direct access to useragent object

=head1 FUNCTIONS

=head2 rpcfault(faultCode, faultString)

Returns hash structure, that may be returned by serverside handler, instead of die. Not exported by default

=head1 CUSTOM TYPES

=head2 sub {{ 'base64' => encode_base64($data) }}

When passing a CODEREF as a value, encoder will simply use the returned hashref as a type => value pair.

=head2 bless( do{\(my $o = encode_base64('test') )}, 'base64' )

When passing SCALARREF as a value, package name will be taken as type and dereference as a value

=head2 bless( do{\(my $o = { something =>'complex' } )}, 'base64' )

When passing REFREF as a value, package name will be taken as type and L<XML::Hash::LX>C<::hash2xml(deref)> would be used as value


=cut

=head1 BUGS & SUPPORT

Bugs reports and testcases are welcome.

It you write your own Enc or UA, I may include it into distribution

If you have propositions for default custom types (see Enc), send me patches

See L<http://rt.cpan.org> to report and view bugs.

=head1 AUTHOR

Mons Anderson, C<< <mons@cpan.org> >>

=head1 COPYRIGHT & LICENSE

Copyright (c) 2008-2009 Mons Anderson.

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


=cut

