The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

==== How to run a SOAP::Daemon under CGI

(for mod_perl see further down)

Example of a XML::Compile CGI script

   Patrick Powell papowell at astart dot com
   Thu Dec 23 2010
   Updated Wed Jun 22 13:14:12 PDT 2011 for 
     XML-Compile-SOAP-Daemon-3.00

This text uses the ~/examples/namesservice/ as a example application. Of
course, you should copy that into your own workspace.

1. Put the Perl Modules, WSDL and schema files in a well known location
     (i.e. - the SOAP directory)
     and make sure they are readable by the HTTPD server:

     mkdir /usr/local/www/SOAP
     chmod 755 /usr/local/www/SOAP
     cp namesservice.wsdl namesservice.xsd *.pm /usr/local/www/SOAP
     chmod 644 /usr/local/www/SOAP/*

2. Edit the nph-server.cgi script and set the 'use lib' entry to the directory
     where you copied the Perl Modules. i.e.:
     use lib '/usr/local/www/SOAP';
     my $schemas = '/usr/local/www/SOAP';

3. You might want to use a lot of debugging at first.
    Set the default 'mode' entry to 'DEBUG' and change the
    dispatcher to put messages into a file.

    vi nph-server.cgi
      Change:
        # dispatcher FILE => 'log', mode => $mode, to => \*STDERR;
        dispatcher FILE => 'log', mode => $mode, to => '/tmp/serverlog'
      Change:
      #my $mode = 0;
      my $mode = 'DEBUG';

4. Put the nph-server.cgi script into a HTTPD directory
   which allows CGI execution (i.e. - the CGI-BIN directory)
   and make sure the script has execute permissions:
     cp nph-server.cgi *.pm /usr/local/www/apache/cgi-bin/
     chmod 755 /usr/local/www/apache/cgi-bin/nph-server.cgi

5. If you are running Apache + ModPerl2 check your Apache httpd.conf
   file and find the mod_perl configuration setup:
    
    <IfModule mod_perl.c>
       PerlTaintCheck On
       # PerlSendHeaders
       PerlOptions -ParseHeaders
       PerlPostConfigRequire /usr/local/www/apache22/startup.pl
    </IfModule>

    You MUST turn ParseHeaders OFF, i.e. PerlOptions -ParseHeaders
    You MUST remove or turn off the PerlSendHeaders function
    If you make any changes, restart Apache:
      apachectl restart

6. Check the version of CGI installed on your system.  This MUST
   be at least 3.53:
    perl -MCGI -e 'print "$CGI::VERSION\n"'
   You should update the CGI module if it is not.

7. Test to see if you can connect to the HTTPD server and the CGI
   script is executed:

    rm /tmp/soap   # delete the log file
    perl client.pl --server=http://localhost/cgi-bin/nph-server.cgi
 

==== How to run a SOAP::Daemon under mod_perl

Example of a XML::Compile CGI script
   Patrick Powell papowell at astart dot com
   Thu Dec 23 2010

This text uses the ~/examples/namesservice/ as example application. Of
course, you should change that into your own.

You need to create a module, say MyServer.pm, that has all of the content of
this script up to the point where the call to runRequest is made.  The ways
to do this are many and varied.  The following is shortcut to help with this.

1. run the 'create_MyServer' script:
   sh create_MyServer

2. Copy MyServer.pm to the SOAP directory and set read and execute
   permissions

   cp MyServer.pm /usr/local/www/SOAP
   chmod a+rx /usr/local/www/SOAP/*.pm

2. Copy the nph-server2.cgi file to the CGI-BIN directory
   and set read and execute permissions.
   This script contains just enough code to call the runCgiRequest()
   routine in the MyServer.pm module:

   nph-server2.cgi START

   #!/usr/bin/perl
   use lib '/usr/local/www/SOAP';
   use Log::Report   'example', syntax => 'SHORT';
   use CGI;
   use MyServer;
   my $mode = 'DEBUG';
   dispatcher FILE => 'log', mode => $mode, to => "/tmp/soap";
   my $query = CGI->new;
   runCgiRequest( $query );
   exit 0;

   nph-server2.cgi END

   cp nph-server.cgi *.pm /usr/local/www/apache/cgi-bin/
   chmod 755 /usr/local/www/apache/cgi-bin/nph-server.cgi


4. Check that the new script can load the MyServer.pm modules:
   rm /tmp/soap
   /usr/local/www/apache/cgi-bin/nph-server2.cgi

5.  Now run the query:
      rm /tmp/soap
      perl client.pl --server=http://localhost/cgi-bin/nph-server2.cgi
    Look at the log file: more /tmp/soap

6.  If you are running Apache+ModPerl2,  you can preload the MyServer
    module and precompile (almost) all of the code.  Edit your Apache
    httpd.conf file and find the mod_perl configuration setup:
    
    <IfModule mod_perl.c>
       PerlTaintCheck On
       PerlOptions -ParseHeaders
       PerlPostConfigRequire /usr/local/www/apache22/startup.pl
    </IfModule>

    Now edit that startup.pl file and add the following:

      use lib '/usr/local/www/SOAP';
      use MyServer;
      chmod 0666, "/tmp/soap" if -f "/tmp/soap";
      1;

   The reason for the chmod is that the startup script runs as ROOT
   but the CGI scripts run as the Apache User (usually 'www')

7. Remove any log files and Restart Apache:
      rm /tmp/soap
      apachectl restart
   Now check the log file:
      more /tmp/soap
   and you should see 
      trace: register prefix wsdl for 'http://schemas.xmlsoap.org/wsdl/'
      trace: register prefix soap for 'http://schemas.xmlsoap.org/wsdl/soap/'
      trace: register prefix http for 'http://schemas.xmlsoap.org/wsdl/http/'
      trace: initialize SOAP11 operations for WSDL11

8.  Now run the query:
      rm /tmp/soap
      perl client.pl --server=http://localhost/cgi-bin/nph-server2.cgi

    Now check the log file:
      more /tmp/soap
   and you should see 
        trace: REQUEST$VAR1 = bless( {
         '_protocol' => 'HTTP/1.1',
         '_content' => '<?xml version="1.0" encoding="UTF-8"?>
   We are using the compiled code for $daemon generated by MyServer.pm

Caveats and Warnings:
   Apache and ModPerl do not always set the current directory of the 
   running CGI script to the directory where the script is located.
   This is partly due to the effect of using Threads.  Rather than trying
   to fix a large number of (non-Apache) libraries, etc, the Apache and Mod_perl
   developers simply state that you should assume that the current
   directory is not the one in which the CGI script is executing.

   This gets even worse when you combine ModPerl and startup scripts.
   The Mod_perl developers explicitly warn that the current directory
   is NOT the directory where the startup script is located.

   Finally, the startup script is executed as ROOT, not as the
   Apache user/group while the CGI scripts are exectuted as the
   Apache user/group.  This can lead to issues if you open log files
   at startup time and then use them at run time.