The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

CAM::SOAPApp - SOAP application framework

LICENSE

Copyright 2006 Clotho Advanced Media, Inc., <cpan@clotho.com>

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

SYNOPSIS

Do NOT subclass from this module to create your SOAP methods! That would make a big security hole. Instead, write your application like this example:

  use CAM::SOAPApp;
  SOAP::Transport::HTTP::CGI
    -> dispatch_to('My::Class')
    -> handle;
  
  package My::Class;
  our @ISA = qw(SOAP::Server::Parameters);
  sub isLeapYear {
     my $pkg = shift;
     my $app = CAM::SOAPApp->new(soapdata => \@_);
     if (!$app) {
        CAM::SOAPApp->error('Internal', 'Failed to initialize the SOAP app');
     }
     my %data = $app->getSOAPData();
     if (!defined $data{year}) {
        $app->error('NoYear', 'No year specified in the query');
     }
     if ($data{year} !~ /^\d+$/) {
        $app->error('BadYear', 'The year must be an integer');
     }
     my $leapyear = ($data{year} % 4 == 0 && 
                     ($data{year} % 100 != 0 || 
                      $data{year} % 400 == 0));
     return $app->response(leapyear => $leapyear ? 1 : 0);
  }

DESCRIPTION

CAM::SOAPApp is a framework to assist SOAP applications. This package abstracts away a lot of the tedious interaction with SOAP and the application configuration state. CAM::SOAPApp is a subclass of CAM::App and therefore inherits all of its handy features.

When you create a class to hold your SOAP methods, that class should be a subclass of SOAP::Server::Parameters. It should NOT be a subclass of CAM::SOAPApp. If you were to do the latter, then all of the CAM::App and CAM::SOAPApp methods would be exposed as SOAP methods, which would be a big security hole, so don't make that mistake.

OPTIONS

When loading this module, there are a few different options that can be selected. These can be mixed and matched as desired.

use CAM::SOAPApp;

This initializes SOAPApp with all of the default SOAP::Lite options.

use CAM::SOAPApp (lenient => 1);

This tweaks some SOAP::Lite and environment variables to make the server work with SOAP-challenged clients. These tweaks specifically enable HTTP::CGI and HTTP::Daemon modes for client environments which don't offer full control over their HTTP channel (like Flash and Apple Sherlock 3).

Specifically, the tweaks include the following:

Content-Type

Sets Content-Type to text/xml if it is not set or is set incorrectly.

SOAPAction

Replaces missing SOAPAction header fields with ''.

Charset

Turns off charset output for the Content-Type (i.e. 'text/xml' instead of 'text/xml; charset=utf-8').

HTTP 500

Outputs HTTP 200 instead of HTTP 500 for faults.

XML trailing character

Adds a trailing '>' to the XML if one is missing. This is to correct a bug in the way Safari 1.0 posts XML from Flash.

use CAM::SOAPApp (handle => PACKAGE);

(Experimental!) Kick off the SOAP handler automatically. This runs the following code immediately:

  SOAP::Transport::HTTP::CGI
    -> dispatch_to(PACKAGE)
    -> handle;

Note that you must load PACKAGE before this statement.

METHODS

CAM::SOAPApp->new(soapdata => \@array)

Create a new application instance. The arguments passed to the SOAP method should all be passed verbatim to this method as a reference, less the package reference. This should be like the following:

  sub myMethod {
     my $pkg = shift;
     my $app = CAM::SOAPApp->new(soapdata => \@_);
     ...
  }
$app->getSOAPData()

Returns a hash of data passed to the application. This is a massaged version of the soapdata array passed to new().

$app->response($key1 => $value1, $key2 => $value2, ...)

Prepare data to return from a SOAP method. For example:

  sub myMethod {
     ...
     return $app->response(year => 2003, month => 3, date => 26);
  }

yields SOAP XML that looks like this (namespaces and data types omitted for brevity):

  <Envelope>
    <Body>
      <myMethodResponse>
        <year>2003</year>
        <month>3</month>
        <date>26</date>
      </myMethodResponse>
    </Body>
  </Envelope>
$app->error()
$app->error($faultcode)
$app->error($faultcode, $faultstring)
$app->error($faultcode, $faultstring, $key1 => $value1, $key2 => $value2, ...)

Emit a SOAP fault indicating a failure. The faultcode should be a short, computer-readable string (like "Error" or "Denied" or "BadID"). The faultstring should be a human-readable string that explains the error. Additional values are encapsulated as detail fields for optional context for the error. The result of this method will look like this (namespaces and data types omitted for brevity).

  <Envelope>
    <Body>
      <Fault>
        <faultcode>$faultcode</faultcode>
        <faultstring>$faultstring</faultstring>
        <detail>
          <data>
            <$key1>$value1</$key1>
            <$key2>$value2</$key2>
            ...
          </data>
        <detail>
      </Fault>
    </Body>
  </Envelope>
$app->encodeHash(\%hash)

This is a helper function used by response() to encode hash data into a SOAP-friendly array of key-value pairs that are easily transformed into XML tags by SOAP::Lite. You should generally use response() instead of this function unless you have a good reason.

AUTHOR

Clotho Advanced Media Inc., cpan@clotho.com

Primary developer: Chris Dolan