|
NAMESOAP::Transport - an abstract class extended by more specialized transport modulesDESCRIPTIONObjects of the SOAP::Transport class manage two roles: they manage both the parameters related to transport as set through the containing SOAP::Lite object, and they abstract the selection and loading of an appropriate transport module. This is done with an AUTOLOAD function within the class that intercepts all methods beyond the two defined next and reroutes them to the underlying transport implementation code.METHODS
SOAP Transport Sub-ClassesBecause the bulk of the work is done within the "SOAP::Lite" module itself, many of the transport-level modules are very simple in their implementations. Transport modules are expected to define both client and server classes within their files. If a module defines only one of the types, it is assumed that the transport protocol itself supports only that side of the conversation. An example is SOAP::Transport::FTP, which provides only a "SOAP::Transport::FTP::Client" class."SOAP::Transport::FTP" - Client class only "SOAP::Transport::HTTP" - Client, and server classes for CGI, FCGI, Daemon and mod_perl "SOAP::Transport::IO" - Server class only "SOAP::Transport::JABBER" - Server and Client classes "SOAP::Transport::LOCAL" - Client class only "SOAP::Transport::MAILTO" - Client class only "SOAP::Transport::MQ" - Server and Client classes "SOAP::Transport::POP3" - Server class only "SOAP::Transport::TCP" - Server and Client classes METHODSEach SOAP::Transport sub-class is expected to define (or inherit, if it is subclassing another transport class) at least two methods. Any newly developed transport classes are also expected to adhere to this interface. Clients are expected to implement the "new" and "send_receive" methods, and servers are expected to implement the "new" and "handle" methods. Here they are:
SOAP::Transport::HTTPThe most commonly used transport module is the HTTP implementation. This is loaded whenever an endpoint is given that starts with the characters, http:// or https://. This is also the most involved of the transport modules, defining not only a client class but several different server classes as well.HTTP PROXY SETTINGS Because "SOAP::Client" inherits from "LWP::UserAgent", you can use any of "LWP::UserAgent"'s proxy settings. For example: SOAP::Lite->proxy("http://endpoint.server/", proxy => ["http" => "http://my.proxy.server"]); or $soap->transport->proxy("http" => "http://my.proxy.server"); The above code samples should specify a proxy server for you. And should you use "HTTP_proxy_user" and "HTTP_proxy_pass" for proxy authorization, "SOAP::Lite" will handle it properly. HTTP BASIC AUTHENTICATION HTTP Basic authentication is accomplished by overriding the get_basic_credentials subroutine in "LWP::UserAgent" (which "SOAP::Transport::HTTP::Client" is a subclass): BEGIN { sub SOAP::Transport::HTTP::Client::get_basic_credentials { return 'username' => 'password'; } } COOKIE-BASED AUTHENTICATION use HTTP::Cookies; my $cookies = HTTP::Cookies->new(ignore_discard => 1); # you may also add 'file' if you want to keep them between sessions my $soap = SOAP::Lite->proxy('http://localhost/'); $soap->transport->cookie_jar($cookies); Or, alternatively, you can do the above on a single line: $soap->proxy('http://localhost/', cookie_jar => HTTP::Cookies->new(ignore_discard => 1)); Cookies will be taken from the response and provided to the request. You may access and manipulate cookies received, as well as add cookies of your own by using the "HTTP::Cookies" interfaces. SSL CERTIFICATE AUTHENTICATION The default SSL implementation for the HTTP client library LWP::UserAgent used by SOAP::Lite is IO::Socket::SSL. To enable certificate based authentication, you'll have to pass your certificate and key as additional options to the proxy() method like this: $soap->proxy( $url, ssl_opts => { SSL_cert_file => 'client-cert.pem', SSL_key_file => 'client-key.pem' }); Or you can set them later like this: $soap->transport->ssl_opts( SSL_cert_file => 'client-cert.pem', SSL_key_file => 'client-key.pem' ); If you're using Crypt::SSLeay, the following applies: To get certificate authentication working you need to set three environment variables: "HTTPS_CERT_FILE", "HTTPS_KEY_FILE", and optionally "HTTPS_CERT_PASS". This can be done either through the command line, or directly within your Perl script using the $ENV variable: $ENV{HTTPS_CERT_FILE} = 'client-cert.pem'; $ENV{HTTPS_KEY_FILE} = 'client-key.pem'; These settings are referenced by "Crypt::SSLeay". Other options (e.g. CA peer verification) can be specified in a similar way. See Crypt::SSLeay documentation for more information. Please note that you probably should not be using Crypt::SSLeay because it does not perform hostname verification; LWP::UserAgent uses IO::Socket::SSL by default. See also <https://metacpan.org/pod/Crypt::SSLeay#DO-YOU-NEED-Crypt::SSLeay>. Those who would like to use encrypted keys may find the following thread in the SOAP::Lite newsgroup helpful: http://groups.yahoo.com/group/soaplite/message/729 COMPRESSION SOAP::Lite provides you with the option for enabling compression over the wire using HTTP only in both the server and client contexts, provided that you have Compress::Zlib installed. Compression and decompression is done transparently to your application. A server will respond with an encoded/compressed message only if the client has asserted that it can accept it (indicated by client sending an "Accept-Encoding" HTTP header with a 'deflate' or '*' value). "SOAP::Lite" clients all have fallback logic implemented so that if a server doesn't understand the specified encoding (i.e. "Content-Encoding: deflate") and returns the proper HTTP status code (415 NOT ACCEPTABLE), the client will repeat the request without using encoding/compression. The client will then store this server in a per-session cache, so that all subsequent requests to that server will be transmitted without encoding. Compression is enabled on the client side by specifying the "compress_threshold" option, and if the size of the current request exceeds that threshold. Client Code Sample print SOAP::Lite ->uri('http://localhost/My/Parameters') ->proxy('http://localhost/', options => {compress_threshold => 10000}) ->echo(1 x 10000) ->result; Servers will respond with a compressed message if the "compress_threshold" option has been specified, if the size of the current response exceeds that threshold, and if the calling client transmitted the proper "Accept-Encoding" HTTP Header. Server Code Sample my $server = SOAP::Transport::HTTP::CGI ->dispatch_to('My::Parameters') ->options({compress_threshold => 10000}) ->handle; See also: Compress::Zlib SOAP::Transport::HTTP::Client Inherits from: SOAP::Client, LWP::UserAgent (from the LWP package). With this class, clients are able to use HTTP for sending messages. This class provides just the basic new and send_receive methods. Objects of this class understand the compress_threshold option and use it if the server being communicated to also understands it. CHANGING THE DEFAULT USERAGENT CLASS By default, "SOAP::Transport::HTTP::Client" extends "LWP::UserAgent". But under some circumstances, a user may wish to change the default UserAgent class with their in order to better handle persist connections, or to "LWP::UserAgent::ProxyAny", for example, which has better Win32/Internet Explorer interoperability. One can use the code below as an example of how to change the default UserAgent class. use SOAP::Lite; use SOAP::Transport::HTTP; $SOAP::Transport::HTTP::Client::USERAGENT_CLASS = "My::UserAgent"; my $client = SOAP::Lite->proxy(..)->uri(..); my $som = $client->myMethod(); There is one caveat, however. The UserAgent class you use, MUST also be a subclass of "LWP::UserAgent". If it is not, then "SOAP::Lite" will issue the following error: "Could not load UserAgent class <USERAGENT CLASS>." HTTP-KEEP-ALIVE, TIMEOUTS, AND MORE Because "SOAP::Transport::HTTP::Client" extends "LWP::UserAgent", all methods available "LWP::UserAgent" are also available to your SOAP Clients. For example, using "LWP::UserAgent" HTTP keep alive's are accomplished using the following code: my $ua = LWP::UserAgent->new( keep_alive => 1, timeout => 30 ); Therefore, the same initialization parameters you would pass to "LWP::UserAgent" can also be passed to your SOAP::Lite client's "proxy" subroutine like so: my $soap = SOAP::Lite ->uri($uri) ->proxy($proxyUrl, timeout => 30, keep_alive => 1, ); This is true for all initialization parameters and methods of "LWP::UserAgent". METHODS
SOAP::Transport::HTTP::Server Inherits from: SOAP::Server. This is the most basic of the HTTP server implementations. It provides the basic methods, new and handle. The handle method's behavior is defined here, along with other methods specific to this class. The role of this class is primarily to act as a superclass for the other HTTP-based server classes.
SOAP::Transport::HTTP::CGI Inherits from: SOAP::Transport::HTTP::Server. This class is a direct subclass of SOAP::Transport::HTTP::Server and defines no additional methods. It includes logic in its implementation of the handle method that deals with the request headers and parameters specific to a CGI environment. EXAMPLE CGI The following code sample is a CGI based Web Service that converts celsius to fahrenheit: #!/usr/bin/perl use SOAP::Transport::HTTP; SOAP::Transport::HTTP::CGI ->dispatch_to('C2FService') ->handle; BEGIN { package C2FService; use vars qw(@ISA); @ISA = qw(Exporter SOAP::Server::Parameters); use SOAP::Lite; sub c2f { my $self = shift; my $envelope = pop; my $temp = $envelope->dataof("//c2f/temperature"); return SOAP::Data->name('convertedTemp' => (((9/5)*($temp->value)) + 32)); } } EXAMPLE APACHE::REGISTRY USAGE Using a strictly CGI based Web Service has certain performance drawbacks. Running the same CGI under the Apache::Registery system has certain performance gains. httpd.conf Alias /mod_perl/ "/Your/Path/To/Deployed/Modules" <Location /mod_perl> SetHandler perl-script PerlHandler Apache::Registry PerlSendHeader On Options +ExecCGI </Location> soap.cgi use SOAP::Transport::HTTP; SOAP::Transport::HTTP::CGI ->dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method') ->handle; WARNING: Dynamic deployments with "Apache::Registry" will fail because the module will be only loaded dynamically the first time. Subsequent calls will produce "denied access" errors because once the module is already in memory "SOAP::Lite" will bypass dynamic deployment. To work around this, simply specify both the full PATH and MODULE name in "dispatch_to()" and the module will be loaded dynamically, but will then work as if under static deployment. See examples/server/soap.mod_cgi as an example. SOAP::Transport::HTTP::Daemon Inherits from: SOAP::Transport::HTTP::Server. The SOAP::Transport::HTTP::Daemon class encapsulates a reference to an object of the HTTP::Daemon class (from the LWP package). The class catches methods that aren't provided locally or by the superclass and attempts to call them on the HTTP::Daemon object. Thus, all methods defined in the documentation for that class are available to this class as well. Any that conflict with methods in SOAP::Transport::HTTP::Server (such as product_tokens) go to the superclass. Additionally, the behavior of the handle method is specific to this class:
REUSING SOCKETS ON RESTART Often when implementing an HTTP daemon, sockets will get tied up when you try to restart the daemon server. This prevents the server from restarting. Often users will see an error like "Cannot start server: port already in use." To circumvent this, instruct SOAP::Lite to reuse open sockets using "Reuse => 1": my $daemon = SOAP::Transport::HTTP::Daemon -> new (LocalPort => 80000, Reuse => 1) EXAMPLE DAEMON SERVER use SOAP::Transport::HTTP; # change LocalPort to 81 if you want to test it with soapmark.pl my $daemon = SOAP::Transport::HTTP::Daemon -> new (LocalAddr => 'localhost', LocalPort => 80) # specify list of objects-by-reference here -> objects_by_reference(qw(My::PersistentIterator My::SessionIterator My::Chat)) # specify path to My/Examples.pm here -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method') ; print "Contact to SOAP server at ", $daemon->url, "\n"; $daemon->handle; SOAP::Transport::HTTP::Apache Inherits from: SOAP::Transport::HTTP::Server. This class provides an integration of the SOAP::Server base class with the mod_perl extension for Apache. To work as a location handler, the package provides a method called handler, for which handle is made an alias. The new method isn't functionally different from the superclass. Here are the other methods provided by this class:
EXAMPLE APACHE MOD_PERL SERVER See examples/server/Apache.pm and Apache::SOAP for more information. httpd.conf <Location /soap> SetHandler perl-script PerlHandler SOAP::Apache PerlSetVar options "compress_threshold => 10000" </Location> SOAP::Apache.pm package SOAP::Apache; use SOAP::Transport::HTTP; my $server = SOAP::Transport::HTTP::Apache ->dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method'); sub handler { $server->handler(@_) } 1; See also Apache::SOAP. SOAP::Transport::HTTP::FCGI Inherits from: SOAP::Transport::HTTP::CGI. This is an extension of the SOAP::Transport::HTTP::CGI that implements the differences needed for the FastCGI protocol. None of the methods are functionally different. SOAP::Transport::IOThe SOAP::Transport::IO-based class allows for a sort of I/O proxying by allowing the application to configure what files or filehandles are used. This module supplies only a server class.SOAP::Transport::IO::Server Inherits from: SOAP::Server. The server class defined here inherits all methods from SOAP::Server, and adds two additional methods specific to the nature of the class:
SOAP::Transport::LOCALThe SOAP::Transport::LOCAL module is designed to provide a no-transport client class for tracing and debugging communications traffic. It links SOAP::Client and SOAP::Server so that the same object that "sends" the request also "receives" it.SOAP::Transport::LOCAL::Client Inherits from: SOAP::Client, SOAP::Server. The implementations of the new and send_receive methods aren't noticeably different in their interface. Their behavior warrants description, however:
SOAP::Transport::MAILTOThis transport class manages SMTP-based sending of messages from a client perspective. It doesn't provide a server class. The class gets selected when a client object passes a URI to proxy or endpoint that starts with the characters, mailto:.SOAP::Transport::MAILTO::Client Inherits from: SOAP::Client. The client class for this protocol doesn't define any new methods. The constructor functions in the same style as the others class constructors. The functionality of the send_receive method is slightly different from other classes, however. When invoked, the send_receive method uses the MIME::Lite package to encapsulate and transmit the message. Because mail messages are one-way communications (the reply being a separate process), there is no response message to be returned by the method. Instead, all the status-related attributes (code, message, status, is_success) are set, and no value is explicitly returned. SOAP::Transport::POP3POP3 support is limited to a server implementation. Just as the MAILTO class detailed earlier operates by sending requests without expecting to process a response, the server described here accepts request messages and dispatches them without regard for sending a response other than that which POP3 defines for successful delivery of a message.SOAP::Transport::POP3::Server Inherits from: SOAP::Server. The new method of this class creates an object of the Net::POP3 class to use internally for polling a specified POP3 server for incoming messages. When an object of this class is created, it expects an endpoint to be specified with a URI that begins with the characters pop:// and includes user ID and password information as well as the hostname itself. The handle method takes the messages present in the remote mailbox and passes them (one at a time) to the superclass handle method. Each message is deleted after being routed. All messages in the POP3 mailbox are presumed to be SOAP messages. Methods for the Net::POP3 object are detected and properly routed, allowing operations such as $server->ping( ). This means that the endpoint string doesn't need to provide the user ID and password because the login method from the POP3 API may be used directly. ACKNOWLEDGEMENTSSpecial thanks to O'Reilly publishing which has graciously allowed SOAP::Lite to republish and redistribute large excerpts from Programming Web Services with Perl, mainly the SOAP::Lite reference found in Appendix B.COPYRIGHTCopyright (C) 2000-2004 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. AUTHORSPaul Kulchenko (paulclinger@yahoo.com)Randy J. Ray (rjray@blackperl.com) Byrne Reese (byrne@majordojo.com)
Visit the GSP FreeBSD Man Page Interface. |