Subject: | Issues when request element has properties named 'Header' and 'Body'. |
Date: | Mon, 25 Sep 2017 22:51:41 +0000 |
To: | "bug-XML-Compile-SOAP [...] rt.cpan.org" <bug-XML-Compile-SOAP [...] rt.cpan.org> |
From: | Jordan Ayers <jordan.ayers [...] paydia.com> |
Hi,
I've used XML::Compile::SOAP as part of an interface to some unusual SOAP services. While I've been able to interact with most without changes to the module, the built in special handling of 'Header' and 'Body' properties appear to be incompatible with one set of services. I have a patch (copy included below) that covers my needs, but was wondering if an option to disable this behavior on a specific request or action could be added to the module.
Basic structure of the needed request:
<Envelope><Body>
<FooRequest>
<Header prop1="a" prop2="b" />
<Body>
<Bar>123</Bar>
</Body>
</FooRequest>
</Body></Envelope>
Basic structure of client code:
my $wsdl = XML::Compile::WSDL11->new('SomeServices.wsdl');
$wsdl->importDefinitions('SomeService.xsd');
my $foo_call = $wsdl->compileClient('Operation_Foo', server => $server_address);
my ($res, $trace) = $foo_call->({
Header => { prop1 => 'a', prop2 => 'b' },
Body => { Bar => '123' },
});
But this produces something like:
<Envelope><Header /><Body /></Envelope>
I also tried using { Body => { FooRequest => { Header => ..., Body => ... } } for the call, but that produced <Envelope><Body /></Envelope>. If there's another way to submit this kind of request, I haven't found it yet.
I was only implementing client side code; no testing was done related to generating server code. Issues appear to be only on the message building side of things; I found workarounds for any issues parsing responses without changes to this module.
Environment:
I'm running this under perl 5.24.2 on CentOS 6. The service files appear to be SOAP 1.1 services (using http://schemas.xmlsoap.org/soap/, http://schemas.xmlsoap.org/soap/encoding/, etc.). The actual wsdl/xsd files are probably under an NDA; if it matters, I could try to put together definition files for the work-alike example above instead. SOAP modules in use for the client code:
XML::Compile::WSDL11 3.06
XML::Compile::SOAP, XML::Compile::SOAP11, XML::Compile::Transport::SOAPHTTP (this package, version 3.22)
This patch moves the problem from one unlikely name collision to another. A better interface for such a switch would be as an option to $wsdl->compileClient(), but I am not familiar with what would be needed to implement that. This patch allows the following code to produce the desired request:
my ($res, $trace) = $foo_call->({
PassHeaderAndBody => {},
Header => { prop1 => 'a', prop2 => 'b' },
Body => { Bar => '123' },
});
diff against XML::Compile::SOAP 3.22:
--- a/lib/XML/Compile/SOAP.pm 2017-06-30 03:05:06.000000000 -0600
+++ b/lib/XML/Compile/SOAP.pm 2017-09-25 15:49:04.000000000 -0500
@@ -100,6 +100,9 @@
my $env = $xml->isa('XML::LibXML::Document') ? $xml->documentElement :$xml;
my (@header, @body, $wsa_action);
+# Add an off switch for this behavior...
+my($skip) = $env->getChildrenByLocalName('PassHeaderAndBody');
+if ( !$skip ) {
if(my ($header) = $env->getChildrenByLocalName('Header'))
{ @header = map { $_->isa('XML::LibXML::Element') ? type_of_node($_) : ()}
$header->childNodes;
@@ -114,6 +117,7 @@
{ @body = map { $_->isa('XML::LibXML::Element') ? type_of_node($_) : () }
$body->childNodes;
}
+}
+{ header => \@header
, body => \@body
@@ -177,7 +181,13 @@
|| XML::LibXML::Document->new('1.0', $charset || 'UTF-8');
my %data;
- $data{$_} = delete $copy{$_} for qw/Header Body/;
+ # Add an off switch for this behavior...
+ if ( defined $copy{PassHeaderAndBody} ) {
+ delete $copy{PassHeaderAndBody};
+ }
+ else{
+ $data{$_} = delete $copy{$_} for qw/Header Body/;
+ }
$data{Body} ||= {};
foreach my $label (@$hlabels)
Jordan Ayers
Chief Software Engineer
[1471356788247_PastedImage]
Jordan.Ayers@COREcashless.com<mailto:Jordan.Ayers@COREcashless.com>
www.COREcashless.com
Download OutlookEmoji-1471356788247_PastedImagef0472531-6874-4567-9e2b-6ec10c41dcb1.png
image/png 5.7k
image/png 5.7k