[Xml-compile] Timeouts for XML::Compile::WSDL

Mark Overmeer mark at overmeer.net
Mon Feb 1 23:22:15 GMT 2010


Partial answer.

* Titi Ala'ilima (titi at leadkarma.com) [100129 21:22]:
> The thing is, the address error was difficult to track down because it was
> buried inside the invocation of the compiled operation.  The error that I saw
> was: 
>     error: answer is not xml but `text/html'

When things are configured improperly, you can receive any kind of answer.
Problem is that XML processors do expect XML answers.  SOAP has nothing
in its protocol for errors caused by proxies...

> because I have a web server running on localhost that returned HTML. So the
> error message was not helpful and I had to go to great lengths to discover
> what was happening.  Whereas an error message like 'forgot required
> parameter' would have instantly clued me into what was wrong.

In most cases, the SOAP configuration is coming from a WSDL. SOAP without
WSDL is even worse than SOAP with WSDL. So: when the server is set-up
and works with other clients, you should not see that error with this
module either.  Of course, there could be a soapAction handling bug.

> Such a default is only useful if you're interacting with a SOAP service that
> cares if the header is there but ignores the value of the header, which sounds
> like a rare situation.  And again I had to go to great lengths to discover
> where the value was coming from.

the soapAction header is explicitly only there for proxies.  It shall
not be used the servers.  It's one of the few thing the "NOTES" (specs)
are clear about.

> The default value in the transporter
> overrides any value you try to pass in directly as an option to
> XML::Compile::WSDL11::compileClient.

Ah, the documentation says it is overridable, but it actually isn't.
I'll fix it.

lib/XML/Compile/SOAP11/Operation.pm

  sub _fromWSDL11(@)
  { 
    ...
    my $sop = $b_op->{soap_operation}     || {};
 -  $args{action}    = $sop->{soapAction} || '';
 +  $args{action}  ||= $sop->{soapAction} || '';

There was no parameter to overrule the soapAction from the WSDL.
But to make this work:
    $wsdl->operation('doSend', action => 'hi')

lib/XML/Compile/WSDL.pm

  sub operation(@)
  {  ...
     my $operation = $opclass->_fromWSDL11
     ( name      => $name,
     , kind      => $kind
     ...
     , wsdl      => $self
 +   , action    => $args{action}
     );

    $operation;
}

But it should not be needed: the WSDL should not be wrong.

My regression tests (f.i. t/55wsdlrpcone.t) do test for soapAction
translation into the header.  It does work as expected.
 
> Actually, as I said, the original problem is simply an issue of setting the
> timeout.  Given the accessors I've finally found, here is what I am now using
> (with a little extra logic to make it work across different versions):
> 
>     my $op_obj = $wsdl->operation(operation => $operation, port => $port);;

>     my $address = $get_payout_op->can('endPoints') ? ($get_payout_op->
>     endPoints)[0] : ($get_payout_op->endPointAddresses)[0];

This makes me worry that you use an old version of the module, which
(of course) contains more bugs than the currect version.  What version
are you using?  Anyway, you can also use

      my ($address) = $op_obj->endPoints;

>     my $action = $get_payout_op->can('action') ? $get_payout_op->action :
>     $get_payout_op->soapAction;

      my $action    = $op_obj->action;

> So am I missing something that would make this even simpler?

A problem with the 'timeout' is that it affects the connection: SOAPHTTP
uses an LWP::UserAgent, which implements HTTP/1.1.  LWP is managing
the connections, and not X::C::SOAP... so it is possible that your
'timeout' is too late, because there is already a connection set-up.

Only with the step-wise construction of a call, you can controle
each phase:

   my $ua    = LWP::UserAgent->new(...);
   my $trans = XML::Compile::Transport::SOAPHTTP->(user_agent => $ua);
   my $conn  = $trans->compileClient(action => $action);
   my $call  = $wsdl->operation('doSend')
                    ->compileClient(transporter => $conn);

And so forth... gladly, most steps are generated... usually correctly.
Besides, you can pass close to all parameters to

   my $call  = $wsdl->compileClient('doSend', action => $action);

But I may have missed a few.  I'll have to think how I can simplify
the change of 'timeout'.
-- 

               MarkOv

------------------------------------------------------------------------
       Mark Overmeer MSc                                MARKOV Solutions
       Mark at Overmeer.net                          solutions at overmeer.net
http://Mark.Overmeer.net                   http://solutions.overmeer.net




More information about the Xml-compile mailing list