8.4 Standalone Protocols


Three protocols offer nontraditional ways of sending or receiving requests . SOAP::Transport::IO , for example, provides a server to read requests from a filehandle and send responses to another filehandle. SOAP::Transport::FTP::Client stores a request on the FTP server in a text file. SOAP::Transport::LOCAL::Client lets you integrate a server with your client, so SOAP requests and responses don't travel over a network at all. In this section, we look at all three modules.

8.4.1 SOAP::Transport::IO

The SOAP::Transport::IO module provides only a server class. It is very simple in design and potentially very flexible. A server built from SOAP::Transport::IO::Server reads a single, full request from one file handle and sends the result out on a second file handle. Each time the handle method is called, it expects to read all the data available from the input source. Depending on the type of the input source, the end of the data stream may be signaled by a literal end-of-file marker or a shutdown call on a socket. On the outgoing side, there is no assumption that the file handle should be closed or discarded after sending the response, making it more likely to be reused. Thanks to the universal nature of file handles in Perl, the code doesn't have to provide special-case handling for these different types of input sources.

The potential usefulness of this class is greater than it may appear at first glance. This class makes a good core element for an application that monitors several TCP, UDP, and Unix-domain sockets, sending all incoming requests to the same server instance. Alternately, a daemon built on this class can be responsible for monitoring areas of a filsystem, watching for requests in the form of physical files (see the FTP client in Section 8.4.2).

As an example, the IO class will be used in a much simpler role, that of a Unix-style filter. The code in Example 8-9 is designed to be called from a command line, perhaps as a mail filter or part of a cron task. It reads a single request from standard-input and writes the response to standard output.

Example 8-9. The SOAP::Transport::IO::Server example
 #!/usr/bin/perl     use strict;     use SOAP::Transport::IO; use WishListCustomer::SOAP; use WishListCustomer::Transport         'SOAP::Transport::IO::Server';     my $server = WishListCustomer::Transport     ->new( )     ->dispatch_with({ 'urn:/WishListCustomer' =>                       'WishListCustomer::SOAP' })     ->objects_by_reference('WishListCustomer::SOAP')     ->handle;     exit; 

Because each invocation means fresh loading and compilation of the SOAP application code, this may seem to be a less-than -optimal application, and that is true to some extent. It would be a valid application as part of a larger system, a part that manages filter-oriented or similar tasks while sharing the basic code base and architecture of a larger, more standard SOAP server on an HTTP port.

8.4.2 SOAP::Transport::FTP::Client

The FTP module is designed simply to upload the request as an ordinary text file on a specified server. It is similar to the SOAP::Transport::MAILTO module in that communication is one way in nature. Requests are written remotely based on the full path given in the endpoint.

Because the FTP client represents a one-way transaction, the client from the MAILTO example will be adapted to work in a more generic fashion. Rather than taking just the target POP3 host as a command-line argument, it will be adapted to require a more fully specified endpoint, in the same way the earlier generic client does.

The updated client is shown in Example 8-10. Some logic is applied to the endpoint strings before the client object gets created. A MAILTO endpoint gets a "From" address and subject added. An FTP endpoint is expected to specify only the directory portion of the path; the application creates a filename based on the user ID and a timestamp, which avoids overwriting other files on the same server.

Example 8-10. The generic version of the purchasing client
 #!/usr/bin/perl     use strict;     use WishListCustomer::Client; use Sys::Hostname 'hostname';     my ($user, $passwd, $endpoint) = (shift, shift, shift); die "USAGE: 
 #!/usr/bin/perl use strict; use WishListCustomer::Client; use Sys::Hostname 'hostname'; my ($user, $passwd, $endpoint) = (shift, shift, shift); die "USAGE: $0 username passwd endpoint ISBN [ ISBN... ]\n" unless ($user and $passwd and $endpoint and @ARGV); if (substr($endpoint, 0, 3) eq 'ftp') { my @time = localtime; my $file = sprintf("%s-%02d%02d%02d:%02d%02d.xml", $user, $time[5] % 100, # year $time[4] + 1, # month $time[3], # day $time[2], # hour $time[1]); # minute $endpoint .= '/' unless (substr($endpoint, -1, 1) eq '/'); $endpoint .= $file; } elsif (substr($endpoint, 0, 6) eq 'mailto') { my $hostname = eval { hostname }; $hostname = 'localhost' if $@; $endpoint = "$endpoint?From=$user\@$hostname&Subject=" . 'SOAP'; } else { die "$0: endpoint only supports ftp: and mailto: "; } my $soap = WishListCustomer::Client ->uri('urn:/WishListCustomer') ->proxy($endpoint); $soap->setAuth($user, $passwd); my $result = $soap->PurchaseBooks(\@ARGV); if ($result->fault) { die "$0: Operation failed: " . $result->faultstring; } else { print "Request sent\n"; } exit; 
username passwd endpoint ISBN [ ISBN... ]\n" unless ($user and $passwd and $endpoint and @ARGV); if (substr($endpoint, 0, 3) eq 'ftp') { my @time = localtime; my $file = sprintf("%s-%02d%02d%02d:%02d%02d.xml", $user, $time[5] % 100, # year $time[4] + 1, # month $time[3], # day $time[2], # hour $time[1]); # minute $endpoint .= '/' unless (substr($endpoint, -1, 1) eq '/'); $endpoint .= $file; } elsif (substr($endpoint, 0, 6) eq 'mailto') { my $hostname = eval { hostname }; $hostname = 'localhost' if $@; $endpoint = "$endpoint?From=$user\@$hostname&Subject=" . 'SOAP'; } else { die "
 #!/usr/bin/perl use strict; use WishListCustomer::Client; use Sys::Hostname 'hostname'; my ($user, $passwd, $endpoint) = (shift, shift, shift); die "USAGE: $0 username passwd endpoint ISBN [ ISBN... ]\n" unless ($user and $passwd and $endpoint and @ARGV); if (substr($endpoint, 0, 3) eq 'ftp') { my @time = localtime; my $file = sprintf("%s-%02d%02d%02d:%02d%02d.xml", $user, $time[5] % 100, # year $time[4] + 1, # month $time[3], # day $time[2], # hour $time[1]); # minute $endpoint .= '/' unless (substr($endpoint, -1, 1) eq '/'); $endpoint .= $file; } elsif (substr($endpoint, 0, 6) eq 'mailto') { my $hostname = eval { hostname }; $hostname = 'localhost' if $@; $endpoint = "$endpoint?From=$user\@$hostname&Subject=" . 'SOAP'; } else { die "$0: endpoint only supports ftp: and mailto: "; } my $soap = WishListCustomer::Client ->uri('urn:/WishListCustomer') ->proxy($endpoint); $soap->setAuth($user, $passwd); my $result = $soap->PurchaseBooks(\@ARGV); if ($result->fault) { die "$0: Operation failed: " . $result->faultstring; } else { print "Request sent\n"; } exit; 
: endpoint only supports ftp: and mailto: "; } my $soap = WishListCustomer::Client ->uri('urn:/WishListCustomer') ->proxy($endpoint); $soap->setAuth($user, $passwd); my $result = $soap->PurchaseBooks(\@ARGV); if ($result->fault) { die "
 #!/usr/bin/perl use strict; use WishListCustomer::Client; use Sys::Hostname 'hostname'; my ($user, $passwd, $endpoint) = (shift, shift, shift); die "USAGE: $0 username passwd endpoint ISBN [ ISBN... ]\n" unless ($user and $passwd and $endpoint and @ARGV); if (substr($endpoint, 0, 3) eq 'ftp') { my @time = localtime; my $file = sprintf("%s-%02d%02d%02d:%02d%02d.xml", $user, $time[5] % 100, # year $time[4] + 1, # month $time[3], # day $time[2], # hour $time[1]); # minute $endpoint .= '/' unless (substr($endpoint, -1, 1) eq '/'); $endpoint .= $file; } elsif (substr($endpoint, 0, 6) eq 'mailto') { my $hostname = eval { hostname }; $hostname = 'localhost' if $@; $endpoint = "$endpoint?From=$user\@$hostname&Subject=" . 'SOAP'; } else { die "$0: endpoint only supports ftp: and mailto: "; } my $soap = WishListCustomer::Client ->uri('urn:/WishListCustomer') ->proxy($endpoint); $soap->setAuth($user, $passwd); my $result = $soap->PurchaseBooks(\@ARGV); if ($result->fault) { die "$0: Operation failed: " . $result->faultstring; } else { print "Request sent\n"; } exit; 
: Operation failed: " . $result->faultstring; } else { print "Request sent\n"; } exit;

Again, the transparent nature of how SOAP::Lite clients load the appropriate transport module makes the application much simpler and cleaner. An FTP endpoint looks something like:

 ftp://user:pass@ftp.somewhere.com/path/to/dir 

Normally, the SOAP::Transport::FTP::Client class expects the FTP endpoint to include the final element (the filename). This application provides the last piece before creating the client object. Changing the final else -clause allows the other (bidirectional) transport methods to be accepted for this application as well.

8.4.3 SOAP::Transport::LOCAL::Client

The last of the transport modules provided by SOAP::Lite provides a "local" mode of transport that isn't actually transport at all.

The SOAP::Transport::LOCAL module provides only a client class, but the underlying object actually encapsulates both a client and a server from within the same object. The client handles requests by passing the envelope directly to the handle method it finds in the SOAP::Server class, from which it inherits. The server part of the object is configured to look for any requested classes in the list of directories in @INC .

Using the class itself is naturally somewhat different from the other client or server classes. The main use of this class is to allow applications to test their SOAP interface code. Tests can be run using just local resources, without any real transport traffic.

These tests can be as simple as running methods to check for syntax errors. Alternatively, the code can set various levels of tracing via the trace argument when SOAP::Lite is loaded. Example 8-11 shows a simple application that searches for books by title, using a pattern provided on the command line.

Example 8-11. Using SOAP::Transport::LOCAL for simple tests
 #!/usr/bin/perl     use strict;     use SOAP::Lite +trace => 'method'; use WishListCustomer::SOAP;     my $pattern = shift  'perl'; my $soap = SOAP::Lite->uri('urn:/WishListCustomer')                      ->proxy('local:',                              'dispatch_with' => {                                  'urn:/WishListCustomer' => 'WishListCustomer::SOAP'                               });     my $result = $soap->BooksByTitle($pattern); if ($result->fault) {     die " 
 #!/usr/bin/perl use strict; use SOAP::Lite +trace => 'method'; use WishListCustomer::SOAP; my $pattern = shift  'perl'; my $soap = SOAP::Lite->uri('urn:/WishListCustomer') ->proxy('local:', 'dispatch_with' => { 'urn:/WishListCustomer' => 'WishListCustomer::SOAP' }); my $result = $soap->BooksByTitle($pattern); if ($result->fault) { die "$0: Operation failed: " . $result->faultstring; } my $books = $result->result; format = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>>>>>>>>>>> $result->{title}, $result->{isbn} . print "Books whose title matches '$pattern':\n\n"; for (@$books) { $result = $soap->GetBook($_); # Quietly skip books that cause faults next if ($result->fault); $result = $result->result; write; } exit; 
: Operation failed: " . $result->faultstring; } my $books = $result->result; format = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>>>>>>>>>>> $result->{title}, $result->{isbn} . print "Books whose title matches '$pattern':\n\n"; for (@$books) { $result = $soap->GetBook($_); # Quietly skip books that cause faults next if ($result->fault); $result = $result->result; write; } exit;

Calling dispatch_with was done a little differently in this example. While the SOAP::Transport::LOCAL::Client class does include SOAP::Server in the inheritance path, calling dispatch_with directly on the object triggers the auto-dispatch functionality and attempts to treat it as a remote method. By riding along on the call to proxy, we avoid this. It can also be avoided using the object returned by $soap->transport to call the method.



Programming Web Services with Perl
Programming Web Services with Perl
ISBN: 0596002068
EAN: 2147483647
Year: 2000
Pages: 123

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net