ActivePerl Documentation
|
NAMESOAP::Lite - Client and server side SOAP implementation
SUPPORTED PLATFORMS
SYNOPSIS
# client side
use SOAP::Lite;
print SOAP::Lite
-> uri('http://simon.fell.com/calc')
-> proxy('http://www.razorsoft.net/ssss4c/soap.asp')
-> doubler([10,20,30,50,100])
-> result ->[1];
# the same code with autodispatch:
use SOAP::Lite +autodispatch =>
uri => 'http://simon.fell.com/calc',
proxy => 'http://www.razorsoft.net/ssss4c/soap.asp'
;
print doubler([10,20,30,50,100])->[1];
# code with service description
use SOAP::Lite;
print SOAP::Lite
-> schema('http://www.xmethods.net/sd/StockQuoteService.wsdl')
-> getQuote('MSFT');
# code for SOAP server (CGI):
use SOAP::Transport::HTTP;
SOAP::Transport::HTTP::CGI
-> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
-> handle;
DESCRIPTIONSOAP::Lite is a collection of Perl modules which provides a simple and lightweight interface to the Simple Object Access Protocol (SOAP) both on client and server side. This version of SOAP::Lite supports the SOAP 1.1 specification ( http://www.w3.org/TR/SOAP ). The main features of the library are:
WHERE TO FIND EXAMPLESSee test.pl, examples/*.pl and the module documentation for a client-side examples that demonstrate the serialization of a SOAP request, sending it via HTTP to the server and receiving the response, and the deserialization of the response. See examples/soap.cgi, examples/soap.daemon and examples/My/Apache.pm for server-side implementations.
OVERVIEW OF CLASSES AND PACKAGESThis table should give you a quick overview of the classes provided by the library. SOAP::Lite.pm -- SOAP::Lite -- Main class provides all logic -- SOAP::Transport -- Supports transport architecture -- SOAP::Data -- Provides extensions for serialization architecture -- SOAP::Header -- Provides extensions for header serialization -- SOAP::Parser -- Parses XML file into object tree -- SOAP::Serializer -- Serializes data structures to SOAP package -- SOAP::Deserializer -- Deserializes results of SOAP::Parser into objects -- SOAP::SOM -- Provides access to deserialized object tree -- SOAP::Constants -- Provides access to common constants -- SOAP::Trace -- Provides tracing facilities -- SOAP::Schema -- Provides access and stub(s) for schema(s) -- SOAP::Schema::WSDL -- WSDL implementation for SOAP::Schema -- SOAP::Server -- Handles requests on server side -- SOAP::Server::Object -- Handles objects-by-reference SOAP::Transport::HTTP.pm -- SOAP::Transport::HTTP::Client -- Client interface to HTTP transport -- SOAP::Transport::HTTP::Server -- Server interface to HTTP transport -- SOAP::Transport::HTTP::CGI -- CGI implementation of server interface -- SOAP::Transport::HTTP::Daemon -- Daemon implementation of server interface -- SOAP::Transport::HTTP::Apache -- mod_perl implementation of server interface SOAP::Transport::POP3.pm -- SOAP::Transport::POP3::Server -- Server interface to POP3 protocol SOAP::Transport::MAILTO.pm -- SOAP::Transport::MAILTO::Client -- Client interface to SMTP/sendmail SOAP::Transport::LOCAL.pm -- SOAP::Transport::LOCAL::Client -- Client interface to local transport SOAP::Transport::TCP.pm -- SOAP::Transport::TCP::Server -- Server interface to TCP protocol -- SOAP::Transport::TCP::Client -- Client interface to TCP protocol
SOAP::LiteAll methods that SOAP::Lite provides can be used for both
setting and retrieving values. If you provide no parameters, you will
get current value, and if
$lite = SOAP::Lite
-> uri('http://simon.fell.com/calc')
-> proxy('http://www.razorsoft.net/ssss4c/soap.asp')
;
The order is insignificant and you may call the
$lite = new SOAP::Lite
uri => 'http://simon.fell.com/calc',
proxy => 'http://www.razorsoft.net/ssss4c/soap.asp'
;
Other available methods are:
SOAP::DataYou can use this class if you want to specify a value, a name, atype, a uri or
attributes for SOAP elements (use
SOAP::Data->import('name');
or import SOAP::Data 'name'; and then use An interface for specific attributes is also provided. You can use the
SOAP::Data
->name(c => 3)
->encodingStyle('http://xml.apache.org/xml-soap/literalxml')
will be serialized into: <c SOAP-ENV:encodingStyle="http://xml.apache.org/xml-soap/literalxml" xsi:type="xsd:int">3</c>
SOAP::SerializerUsually you don't need to interact directly with this module. The only case when you need it, it when using autotyping. This feature lets you specify types for your data according to your needs as well as to introduce new data types (like ordered hash for example). You can specify a type with
SOAP::Data->type('ordered_hash' => [a => 1, b => 2])
will be serialized as an ordered hash, using the If you do not specify a type directly, the serialization module will try
to autodefine the type for you according to the priority, check_function (CODE reference), typecast function (METHOD name or CODE reference) For example, if you want to add
$s->typelookup({
%{$s->typelookup},
uriReference => [11, sub { shift =~ m!^http://! }, 'as_uriReference']
});
and add the
sub SOAP::Serializer::as_uriReference {
my $self = shift;
my($value, $name, $type, $attr) = @_;
return [$name, {%{$attr || {}}, 'xsi:type' => 'xsd:uriReference'}, $value];
}
The specified methods will work for both autotyping and direct typing, so you can use either SOAP::Data->type(uriReference => 'http://yahoo.com')> or just 'http://yahoo.com' and it will be serialized into the same type. For more examples see The SOAP::Serializer provides you with
SOAP::SOMSOM gives you access to the deserialized envelope via several methods.
All methods accept a node path (similar to XPath notations).
SOM interprets '/' as the root node, '//' as relative location path
('//Body' will find all bodies in document, as well as
'/Envelope//nums' will find all 'nums' nodes under Envelope node),
'[num]' as node number and '[op num]' with All nodes in nodeset will be returned in document order.
SOAP::SOM also provides methods for direct access to the envelope, the body,
methods and parameters (both in and out). All these methods return real
values (in most cases it will be a hash reference), if called as object
method. Returned values also depend on context: in an array context it will
return an array of values and in scalar context it will return the first
element. So, if you want to access the first output parameter, you can call
if ($som->match('//myparameter')) {
$value = $som->valueof; # can be undef too
} else {
# doesn't exist
}
SOAP::SchemaSOAP::Schema gives you ability to load schemas and create stubs according to these schemas. Different syntaxes are provided:
You can create stub with stubmaker script: perl stubmaker.pl http://www.xmethods.net/sd/StockQuoteService.wsdl and you'll be able to access SOAP services in one line:
perl "-MStockQuoteService qw(:all)" -le "print getQuote('MSFT')"
or dynamically: perl "-MSOAP::Lite schema=>'file:./quote.wsdl'" -le "print getQuote('MSFT')" Other supported syntaxes with
Support for schemas is limited for now. Though module was tested with dozen different schemas it won't understand complex objects and will work only with WSDL.
SOAP::TraceSOAP::Trace provides you with a trace/debug facility for the SOAP::Lite library. To activate it you need to specify a list of traceable events/parts of SOAP::Lite:
use SOAP::Lite +trace =>
qw(list of available traces here);
Available events are: transport -- (client) access to request/response for transport layer dispatch -- (server) shows full name of dispatched call result -- (server) result of method call parameters -- (server) parameters for method call headers -- (server) headers of received message objects -- (both) new/DESTROY calls method -- (both) parameters for '->envelope(method =>' call fault -- (both) parameters for '->envelope(fault =>' call freeform -- (both) parameters for '->envelope(freeform =>' call trace -- (both) trace enters into some important functions debug -- (both) details about transport For example:
use SOAP::Lite +trace =>
qw(method fault);
lets you output the parameter values for all your fault/normal envelopes onto STDERR. If you want to log it you can either redirect STDERR to some file
BEGIN { open(STDERR, '>>....'); }
or (preferably) define your own function for a particular event:
use SOAP::Lite +trace =>
method => sub {'log messages here'}, fault => \&log_faults;
You can share the same function for several events:
use SOAP::Lite +trace =>
method, fault => \&log_methods_and_faults;
Also you can use 'all' to get all available tracing and use '-' in front of an event to disable particular event:
use SOAP::Lite +trace =>
all, -transport; # to get all logging without transport messages
Finally, use SOAP::Lite +trace; will switch all debugging on. You can use 'debug' instead of 'trace'. I prefer 'trace', others 'debug'.
Also use SOAP::Lite;
my $s = SOAP::Lite
-> uri('http://tempuri.org/')
-> proxy('http://beta.search.microsoft.com/search/MSComSearchService.asmx')
-> on_debug(sub{print@_}) # show you request/response with headers
;
print $s->GetVocabulary(SOAP::Data->name('~:Query' => 'something'))
->valueof('//FOUND');
or switch it on individually, with use SOAP::Lite +trace => debug; or
use SOAP::Lite +trace => debug => sub {'do_what_I_want_here'};
Compare this with: use SOAP::Lite +trace => transport; which gives you access to B<actual> request/response objects, so you can even set/read cookies or do whatever you want there. The difference between
FEATURES AND OPTIONS
IN/OUT, OUT PARAMETERS AND AUTOBINDINGSOAP::Lite gives you access to all parameters (both in/out and out) and also does some additional work for you. Lets consider following example:
<mehodResponse>
<res1>name1</res1>
<res2>name2</res2>
<res3>name3</res3>
</mehodResponse>
In that case: $result = $r->result; # gives you 'name1' $paramout1 = $r->paramsout; # gives you 'name2', because of scalar context $paramout1 = ($r->paramsout)[0]; # gives you 'name2' also $paramout2 = ($r->paramsout)[1]; # gives you 'name3' or @paramsout = $r->paramsout; # gives you ARRAY of out parameters $paramout1 = $paramsout[0]; # gives you 'res2', same as ($r->paramsout)[0] $paramout2 = $paramsout[1]; # gives you 'res3', same as ($r->paramsout)[1] Generally, if server returns If the server returns But there is more. If you have in your output parameters a parameter with the same signature (name+type) as in the input parameters this parameter will be mapped into your input automatically. Example: server:
sub mymethod {
shift; # object/class reference
my $param1 = shift;
my $param2 = SOAP::Data->name('myparam' => shift() * 2);
return $param1, $param2;
}
client:
$a = 10;
$b = SOAP::Data->name('myparam' => 12);
$result = $soap->mymethod($a, $b);
After that, server: package My::PingPong;
sub new {
my $self = shift;
my $class = ref($self) || $self;
bless {_num=>shift} => $class;
}
sub next {
my $self = shift;
$self->{_num}++;
}
client:
use SOAP::Lite +autodispatch =>
uri => 'urn:',
proxy => 'http://localhost/'
;
my $p = My::PingPong->new(10); # $p->{_num} is 10 now, real object returned
print $p->next, "\n"; # $p->{_num} is 11 now!, object autobinded
AUTODISPATCHINGWARNING! This feature can have side effects for your application and can affect functionality of other modules/libraries because of overloading UNIVERSAL::AUTOLOAD. All unresolved calls will be dispatched as SOAP calls, however it could be not what you want in some cases. If so, consider using object interface. SOAP::Lite provides an autodispatching feature that lets you create code which looks the same for local and remote access. For example:
use SOAP::Lite +autodispatch =>
uri => 'urn:/My/Examples',
proxy => 'http://localhost/'
;
tells SOAP to 'autodispatch' all calls to the 'http://localhost/' endpoint with the 'urn:/My/Examples' uri. All consequent method calls can look like:
print getStateName(1), "\n";
print getStateNames(12,24,26,13), "\n";
print getStateList([11,12,13,42])->[0], "\n";
print getStateStruct({item1 => 10, item2 => 4})->{item2}, "\n";
As you can see, there is no SOAP specific coding at all. The same logic will work for objects as well: print "Session iterator\n"; my $p = My::SessionIterator->new(10); print $p->next, "\n"; print $p->next, "\n"; This will access the remote My::SessionIterator module, gets an object, and then calls remote methods again. The object will be transferred to the server, the method is executed there and the result (and the modified object!) will be transferred back to the client. Autodispatch will work only if you do not have the same method in your
code. For example, if you have print $p->SOAP::next, "\n"; See You can mix autodispatch and usual SOAP calls in the same code if
you need it. Keep in mind, that calls with SOAP:: prefix should always be a
method call, so if you want to call functions, use Be warned though Perl has very flexible syntax some versions will complain Bareword "autodispatch" not allowed while "strict subs" in use ... if you try to put 'autodispatch' and '=>' on separate lines. So, keep them on the same line, or put 'autodispatch' in quotes:
use SOAP::Lite 'autodispatch' # DON'T use plus in this case
=> ....
;
ACCESSING HEADERS AND ENVELOPE ON SERVER SIDESOAP::Lite gives you direct access to all headers and the whole envelope on the server side. Consider the following code from My::Parameters.pm:
sub byname {
my($a, $b, $c) = @{pop->method}{qw(a b c)};
return "a=$a, b=$b, c=$c";
}
You will get this functionality ONLY if you inherit your class from the SOAP::Server::Parameters class. This should keep existing code working and provides this feature only when you need it. Every method on server side will be called as class/object method, so it will get an object reference or a class name as the first parameter, then the method parameters, and then an envelope as SOAP::SOM object. Shortly: $self [, @parameters] , $envelope If you have a fixed number of parameters, you can simple do: my $self = shift; my($param1, $param2) = @_; and ignore the envelope. If you need access to the envelope you can do: my $envelope = pop; since the envelope is always the last element in the parameters list.
The
my($a, $b, $c) = @{pop->method}{qw(a b c)};
gives you by-name access to your parameters.
SERVICE DEPLOYMENT. STATIC AND DYNAMICLet us scrutinize the deployment process. When designing your SOAP server you
can consider two kind of deployment: static and dynamic.
For both, static and dynamic, you should specify Example for static deployment: use SOAP::Transport::HTTP; use My::Examples; # module is preloaded
SOAP::Transport::HTTP::CGI
# deployed module should be present here or client will get 'access denied'
-> dispatch_to('My::Examples')
-> handle;
Example for dynamic deployment: use SOAP::Transport::HTTP; # name is unknown, module will be loaded on demand
SOAP::Transport::HTTP::CGI
# deployed module should be present here or client will get 'access denied'
-> dispatch_to('/Your/Path/To/Deployed/Modules', 'My::Examples')
-> handle;
For static deployment you should specify the MODULE name directly.
For dynamic deployment you can specify the name either directly (in that
case it will be You should also use static binding when you have several different classes in one file and want to make them available for SOAP calls.
SECURITYDue to security reasons, the current path for perl modules (
OBJECTS-BY-REFERENCESOAP::Lite implements an experimental (yet fully functional) support for
objects-by-reference. You should not see any difference on the client side
when using this. On the server side you should specify the names of the
classes you want to be returned by reference (instead of by value) in the
Garbage collection is done on the server side (not earlier than after 600 seconds of inactivity time), and you can overload the default behavior with specific functions for any particular class. Binding does not have any special syntax and is implemented on server side
(see the differences between My::SessionIterator and My::PersistentIterator).
On the client side, objects will have same type/class as before
(
DEFAULT HANDLERSThe
use SOAP::Lite on_action => sub {sprintf '%s#%s', @_};
and this handler will be the default handler for all your SOAP objects.
You can override it if you specify a handler for a particular object.
See test.pl as example of
INTEROPERABILITY
To use SOAP::Lite client and .NET server
Thanks to Petr Janata (petr.janata@i.cz) for description and examples.
BUGS AND LIMITATIONS
PLATFORMS
AVAILABILITYYou can download the latest version SOAP::Lite for Unix or SOAP::Lite for Win32 ( http://geocities.com/paulclinger/soap.html ). SOAP::Lite is available also from CPAN ( http://search.cpan.org/search?dist=SOAP-Lite ). You are very welcome to write mail to the authors (paulclinger@yahoo.com) with your comments, suggestions, bug reports and complaints.
SEE ALSOthe SOAP manpage SOAP/Perl library from Keith Brown ( http://www.develop.com/soap/ ) or ( http://search.cpan.org/search?dist=SOAP )
COPYRIGHTCopyright (C) 2000 Paul Kulchenko. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
AUTHORPaul Kulchenko (paulclinger@yahoo.com)
|