=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 $/; }; 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, 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 =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 =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 ->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 =head2 registerClass Proxy-method to encoder. See L =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 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 LC<::hash2xml(deref)> would be used as value =head2 customtype( $type, $data ) Easily compose SCALARREF based custom type =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 to report and view bugs. =head1 AUTHOR Mons Anderson, C<< >> =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