Provided by: libxml-compile-soap-perl_3.22-2_all bug

NAME

       XML::Compile::SOAP::FAQ - frequently asked questions

DESCRIPTION

       On this page, a wild collection of questions are answered related to the
       XML::Compile::SOAP modules.  Or better said: let's hope there will be more in the future.
       If you have contributions either in question or as answer, then please contribute via the
       xml mailinglist.

       Also read XML::Compile::FAQ.

   Modifing the messages
       add XML header fields

       Although WSDLs offer a nice way to define header-fields explicitly, quite a number of
       applications require fields which are not described. Also some W3C standards play this
       game.  See XML::Compile::SOAP::WSA for a complex example. A simple example follows here.

         use warnings;
         use strict;

         package XML::Compile::SOAP::MYEXT;
         use base 'XML::Compile::SOAP::Extension';

         use Log::Report;
         use XML::Compile::SOAP::Util      qw/WSDL11/;
         use XML::Compile::Util            qw/pack_type/;

         my $my_ns = 'http://..../';
         my $my_schema_fie = 'aaa.xsd';

         sub wsdl11Init($@)
         {   my ($self, $wsdl, $args) = @_;
             $wsdl->addPrefixes(myprefix => $my_ns);
             $wsdl->importDefinitions($my_schema_file);
             $self;
         }

         sub soap11Operation$$)
         {   my ($self, $op, $args) = @_;
             # towards the server
             $op->addHeader(INPUT
               => "myprefix_$fieldname" => "{$my_ns}$fieldtype");

             # in server answers
             $op->addHeader(OUTPUT => ...);
         }

       With "soap11ClientWrapper()" and "soap11HandlerWrapper()" you can influence the client
       respectively server processing, for instance to fill-in default values.

       adding HTTP headers

       Some applications require to add headers to the HTTP headers sent or check headers which
       are received. SOAP is not about HTTP, so you have to dive deeper in the underlaying
       constructs; you have to construct the code references in more steps, not using the auto-
       generation mechanisms of some objects, by default hidden to you.

       Examples of needs: authentication/cookies in the header, content (crypt) checksums, non-
       standard content-type headers.

       The ::WSDL11 module detects that the soap-http protocol is needed.  (There is also a pure
       http protocol defined in the SOAP spec, which is never used).  When the operation gets
       compiled (with compileClient), the ::SOAPHTTP module is used to create the soap-http
       specific message transport logic. Then, that module uses LWP to do the actual HTTP
       exchange. To be able to access the in- and outgoing messages, you have to reach to that
       LWP::UserAgent.

       Michael Ludwig contributed the following example (slightly adapted) Of course, select your
       own preferences carefully.

         my $ua = LWP::UserAgent->new(timeout => 10);

         # First the HTTP logic
         # defaults when https is used
         $ua->ssl_opts(verify_hostname => 0, keep_alive => 1);

         # Auto-use cookies
         $ua->cookie_jar( {file => $my_jar_file
           , autosave => 1, ignore_discard => 1 });

         # Now, we need the SOAP logic
         my $trans = XML::Compile::Transport::SOAPHTTP
           ->new(user_agent => $ua, address => $srv_url);

         # Finally the message, with explicit transporter
         my $call = $wsdl->compileClient($opname, transport => $trans);

         # Or more operations at the same time
         # $wsdl->compileCalls(transport => $trans);

         # $answer is the decoded XML content.
         my($answer, $trace) = $call->( \%parms );

         # If you need headers from the response HTTP headers.
         my $http_response = $trace->response;
         print $http_response->header('X-Secret');

       You may know the $srv_url to get the address of the server, but you can also ask the
       operation itself. Here a different implementation:

         my $op    = $wsdl->operation($opname);
         my $srv   = ($op->addresses)[0];
         my $trans = XML::Compile::Transport::SOAPHTTP->new(address => $srv
           , timeout => 15, ssl_opts => { verify_hostname => 0 });

         # Now configure the userAgent
         my $ua    = $trans->userAgent;
         ...

         my $call  = $op->compileClient(transport => $trans);
         ...

       The LWP::UserAgent has many useful hooks (<i>Handlers</i>), for instance "request_send"
       and "response_done".

       Even shorter, The next works as well. In the whole XML::Compile::SOAP suite, parameters
       passed on higher levels are passed to all lower levels. Yeh, unclean programming but
       useful.

         my $ua    = $trans->userAgent;
         my $call  = $wsdl->compileClient(transport => $trans
           , user_agent => $ua);

       When you only need to add simple authentication to the headers, you may use the magic of
       LWP: provide your server address into

         http://user:password@example.com/service

       add Basic Auth HTTP header

       An simple example for the previous section, is the often needed basic authentication.  You
       need something like this:

          my $ua = LWP::UserAgent->new(timeout => 10);
          my $call = $wsdl->compileClient($operation, user_agent => $ua
           , transport_hook => \&basic_auth);

          sub basic_auth($$)
          {   my ($request, $trace) = @_;
              $request->authorization_basic($user, $password);
              $ua->request($request);     # returns $response
          }

       That's all.  When you use XML::Compile::Cache to maintain the calls (advised), it would
       look like this:

          $wsdl->compileCalls(user_agent => $ua, transport_hook => \&basic_auth);

   Collection XSD imports
       From a maintenance point of view, it is a very bad idea that some XML client
       implementations load all the required schemas on the moment they start off. The server may
       change the schemas at any moment, which may break the application at any moment. Also,
       network problems will cause the application to break easily. Therefore, XML::Compile
       requires the schemas to be on local disk (although you can use tricks with wget at start-
       up time to voluntarily give-up your stability)

       To collect the imported schema files, you may use this (on the UNIX/Linux prompt)

         wget -c -nv $(cat * |
                       sed -n 's/.*schemaLocation="\([^"]*\)".*/\1/p' |
                       sort -u)

       In your program, you typically start with

         my $wsdl = XML::Compile::WSDL11->new($wsdl_filename);
         $wsdl->importDefinitions([glob "*.xsd"]);

   Using SSL
       Abeltje contributed an SSL usage example, which then got adapted to this:

          use LWP::UserAgent;

          my $wsdl = XML::Compile::WSDL11->new($wsdlfn);

          # LWP 6.00 introduces ssl_opts
          @ENV{keys %lwp5_ssl} = values %lwp5_ssl
              if LWP::UserAgent->VERSION < 6;
          my $ua = LWP::UserAgent->new(ssl_opts => \%lwp6_ssl);

          $wsdl->compileCalls(user_agent => $ua);

       Do not forget to explicitly install "LWP::Protocol::https" !!!

SEE ALSO

       This module is part of XML-Compile-SOAP distribution version 3.22, built on June 30, 2017.
       Website: http://perl.overmeer.net/xml-compile/

       Please post questions or ideas to the mailinglist at
       http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/xml-compile .  For live contact with
       other developers, visit the "#xml-compile" channel on "irc.perl.org".

LICENSE

       Copyrights 2007-2017 by [Mark Overmeer]. For other contributors see ChangeLog.

       This program is free software; you can redistribute it and/or modify it under the same
       terms as Perl itself.  See http://dev.perl.org/licenses/