simbabque
simbabque

Reputation: 54373

Perl: Getting complete request from SOAP::WSDL object

I'm working with SOAP::WSDL and another company's custom WSDL file. Every time they make a change for me and I recreate my modules, something breaks. Finding the problem is rather tedious because I don't find a proper way to access the actual request that is sent to the SOAP server.

The only way to get to the request so far has been to use tcpdump in conjunction with wireshark to extract the request and result. That works, but since I don't have root privileges on the dev machine I have to get an admin over every time I want to do that. I feel there must be another way to get to the HTTP::Request object inside the SOAP::WSDL thing. But if the server returns a fault, I don't even have a response object, but rather a SOAP::WSDL::SOAP::Typelib::Fault11 object that has no visible relation to the request.

I've also tried using the debugger but I'm having trouble finding the actual request part. I've not yet understood how to tell the debuger to skip to a specific part deep inside a complex number of packages.

Upvotes: 3

Views: 1733

Answers (3)

Jim Howard
Jim Howard

Reputation: 176

I stumbled across this, having the same problem myself. I found the answer is using both options that raina77ow listed.

$service->outputxml(1);

returns the whole SOAP envelope xml, but this needs to be combined with

$service->no_dispatch(1);

With no_dispatch set, the SOAP request is printed, instead of the reply from the request. Hopefully this can help others.

Upvotes: 4

simbabque
simbabque

Reputation: 54373

I found a way to at least print out the generated XML code.

First, I looked at SOAP::WSDL::Client as raina77ow suggested. That wasn't what I needed, though. But then I came across SOAP::WSDL::Factory::Serializer. There, it says:

Serializer objects may also be passed directly to SOAP::WSDL::Client by using the set_serializer method.

A little fidgeting and I came up with a wrapper class for SOAP::WSDL::Serializer::XSD which is the default serializer used by SOAP::WSDL. A look at the code helped, too.

Here's the module I wrote. It uses SOAP::WSDL::Serializer::XSD as a base class and overloads the new and serialize methods. While it only passes arguments to new, it grabs the returned XML from serialize and prints it, which suffices for debugging. I'm not sure if there's a way to put it somewhere I can easily get it from.

package MySerializer;
use strict;
use warnings;
use base qw(SOAP::WSDL::Serializer::XSD);

sub new {
  my $self = shift;
  my $class = ref($self) || $self;
  return $self if ref $self;

  # Create the base object and return it
  my $base_object = $class->SUPER::new(@_);
  return bless ($base_object, $class);
}

sub serialize {
  my ($self, $args_of_ref) = @_;

  # This is basically a wrapper function that calls the real Serializer's
  # serialize-method and grabs and prints the returned XML before it
  # giving it back to the caller

  my $xml = ref($self)->SUPER::serialize($args_of_ref);
  print "\n\n$xml\n\n"; # here we go
  return $xml;
}

1;

And here's how I call it:

my $serializer = MySerializer->new();
$self->{'_interface'} = Lib::Interfaces::MyInterface->new();
$self->{'_interface'}->set_serializer($serializer); # comment out to deactivate

It's easy to deactivate. Only put a comment in the set_serializer line.

Of course printing a block of XML to the command line is not very pretty, but it gets the job done. I only need it once in a while why coding/testing, so this is fine I guess.

Upvotes: 0

raina77ow
raina77ow

Reputation: 106443

Have you tried to use SOAP::WSDL::Client tracing methods - and outputxml in particular? It returns the raw SOAP envelope which is to be sent to the server.

You can also use no_dispatch configuration method of SOAP::WSDL package:

When set, call() returns the plain request XML instead of dispatching the SOAP call to the SOAP service. Handy for testing/debugging.

Upvotes: 2

Related Questions