Skip Menu |

This queue is for tickets about the XML-Compile-SOAP CPAN distribution.

Report information
The Basics
Id: 86079
Status: resolved
Priority: 0/
Queue: XML-Compile-SOAP

People
Owner: Nobody in particular
Requestors: mstock [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 2.36
Fixed in: 2.36



Subject: SOAP-Server validation rejects elements if 'elementFormDefault' value of schema and 'form' value of element are different
I received a WSDL file which basically contains something like the following type definition: <wsdl:types> <xsd:schema elementFormDefault="unqualified" targetNamespace="http://example.com/wsdl/formtest/"> <xsd:element name="request"> <xsd:complexType> <xsd:sequence> <xsd:element name="x" minOccurs="0" type="xsd:float" form="qualified" /> </xsd:sequence> </xsd:complexType> </xsd:element> ... </xsd:schema> </wsdl:types> Note that 'elementFormDefault' and 'form' have different values. It seems like the client side of XML-Compile-SOAP does the right thing in this case, i.e. it sends a '<tns:x>1</tns:x>' to the server. The server side, however, rejects this with a faultstring of 'operation request for SOAP11 called with invalid data' and a detail/error of 'element `{http://example.com/wsdl/formtest/}x' not processed for {http://example.com/wsdl/formtest/}request at /SOAP-ENV:Envelope/SOAP-ENV:Body/tns:request/tns:x'. It works fine if 'elementFormDefault' and 'form' are both 'unqualified' or 'qualified', but not if they are different. I'm attaching a test which includes WSDL data that reproduces this behavior (it uses XML::Compile::SOAP::Daemon::PSGI to run the server side). In my understanding of the XML Schema specification, the local 'form' should override the global 'elementFormDefault', so the client seems to do the right thing and the server should process the parameter. I'm currently using XML-Compile 1.34, XML-Compile-SOAP-Daemon 3.06 and XML-Compile-Cache 0.994 on Perl v5.14.2 from Debian Wheezy.
Subject: form_overrides_elementFormDefault.t
use strict; use warnings; use Test::More tests => 16; use XML::Compile::WSDL11; use XML::Compile::SOAP11; use XML::Compile::Transport::SOAPHTTP; use XML::Compile::SOAP::Daemon::PSGI; use Plack::Test; my $wsdl_template = <<EOWSDL; <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="FormTest" xmlns:tns="http://example.com/wsdl/formtest/" targetNamespace="http://example.com/wsdl/formtest/"> <wsdl:types> <xsd:schema elementFormDefault="__FORM01__" targetNamespace="http://example.com/wsdl/formtest/"> <xsd:element name="request"> <xsd:complexType> <xsd:sequence> <xsd:element name="x" minOccurs="0" type="xsd:float" form="__FORM02__" /> <xsd:element name="y" minOccurs="0" type="xsd:float" /> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="response"> <xsd:complexType> <xsd:sequence> <xsd:element name="x" type="xsd:float" /> <xsd:element name="y" type="xsd:float" /> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> </wsdl:types> <wsdl:message name="request"> <wsdl:part element="tns:request" name="parameters" /> </wsdl:message> <wsdl:message name="response"> <wsdl:part element="tns:response" name="parameters" /> </wsdl:message> <wsdl:portType name="example"> <wsdl:operation name="request"> <wsdl:input message="tns:request" name="request" /> <wsdl:output message="tns:response" name="response" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name="exampleSoapBinding" type="tns:example"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="request"> <soap:operation soapAction="request" style="document" /> <wsdl:input name="request"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="response"> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="service"> <wsdl:port binding="tns:exampleSoapBinding" name="defaultPort"> <soap:address location="http://example.com/service" /> </wsdl:port> </wsdl:service> </wsdl:definitions> EOWSDL my @combinations = ( [ 'qualified', 'qualified' ], [ 'unqualified', 'qualified' ], [ 'qualified', 'unqualified' ], [ 'unqualified', 'unqualified' ] ); for my $combination (@combinations) { my $wsdl_data = $wsdl_template; $wsdl_data =~ s{__FORM01__}{$combination->[0]}; $wsdl_data =~ s{__FORM02__}{$combination->[1]}; my $combination_str = 'elementFormDefault="'.$combination->[0].'", ' .'form="'.$combination->[1].'"'; my $wsdl = XML::Compile::WSDL11->new($wsdl_data); my $daemon = XML::Compile::SOAP::Daemon::PSGI->new(); $daemon->operationsFromWSDL($wsdl, callbacks => { request => sub { my ($soap, $data) = @_; my $x = $data->{parameters}->{x} || 0; my $y = $data->{parameters}->{y} || 0; return +{ x => $x, y => $y, }; }, }); my $client = $wsdl->compileClient('request', server => 'localhost:4337', transport_hook => sub { my ($request, $trace) = @_; my $response; test_psgi($daemon->to_app(), sub { my ($cb) = @_; $response = $cb->($request); }); return $response; }, ); my ($answer, $trace) = $client->(); is_deeply($answer->{parameters}, { x => 0, y => 0 }, 'default x and y values, '.$combination_str) or trace($trace); ($answer, $trace) = $client->( x => 1, ); is_deeply($answer->{parameters}, { x => 1, y => 0 }, 'passed x value, default y value, '.$combination_str) or trace($trace); ($answer, $trace) = $client->( y => 1, ); is_deeply($answer->{parameters}, { x => 0, y => 1 }, 'default x value, passed y value, '.$combination_str) or trace($trace); ($answer, $trace) = $client->( x => 1, y => 1, ); is_deeply($answer->{parameters}, { x => 1, y => 1 }, 'passed x and y values, '.$combination_str) or trace($trace); } sub trace { my ($trace) = @_; $trace->printRequest; $trace->printResponse; }
Subject: Re: [rt.cpan.org #86079] SOAP-Server validation rejects elements if 'elementFormDefault' value of schema and 'form' value of element are different
Date: Wed, 12 Jun 2013 10:07:05 +0200
To: Manfred Stock via RT <bug-XML-Compile-SOAP [...] rt.cpan.org>
From: Mark Overmeer <secretaris [...] nluug.nl>
* Manfred Stock via RT (bug-XML-Compile-SOAP@rt.cpan.org) [130612 07:19]: Show quoted text
> Wed Jun 12 03:19:40 2013: Request 86079 was acted upon. > Transaction: Ticket created by MSTOCK > Queue: XML-Compile-SOAP > Subject: SOAP-Server validation rejects elements if 'elementFormDefault' > value of schema and 'form' value of element are different
Your explanation of the problem looks correct. I know that the parser correctly handles the form attribute, however the "operation switch" may not... A soap message does not contain the name of the operation, so that must be detected based on the content of the body, which may be quite expensive. Stupid design. I hope to find time today to fix it. -- Regards, MarkOv ------------------------------------------------------------------------ Mark Overmeer MSc MARKOV Solutions Mark@Overmeer.net solutions@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
Subject: Re: [rt.cpan.org #86079] SOAP-Server validation rejects elements if 'elementFormDefault' value of schema and 'form' value of element are different
Date: Thu, 13 Jun 2013 00:04:17 +0200
To: Manfred Stock via RT <bug-XML-Compile-SOAP [...] rt.cpan.org>
From: Mark Overmeer <secretaris [...] nluug.nl>
* Manfred Stock via RT (bug-XML-Compile-SOAP@rt.cpan.org) [130612 07:19]: Show quoted text
> Wed Jun 12 03:19:40 2013: Request 86079 was acted upon. > Transaction: Ticket created by MSTOCK > Queue: XML-Compile-SOAP > Subject: SOAP-Server validation rejects elements if 'elementFormDefault' > value of schema and 'form' value of element are different
Found it. Thanks for your more than excellent report. The cause is in XML::Compile, the base. It was missing to look at the 'form' attribute on one spot. In XML/Compile/Schema.pm change sub particleElement($) .... my $fullname = pack_type $self->{tns}, $name; - my $nodetype = $self->{elems_qual} ? $fullname : $name; + my $form = $node->getAttribute('form'); + my $qual + = !defined $form ? $self->{elems_qual} + : $form eq 'qualified' ? 1 + : $form eq 'unqualified' ? 0 + : error __x"form must be (un)qualified, not {form} at {where}" + , form => $form, where => $tree->path, _class => 'schema'; + my $nodetype = $qual ? $fullname : $name; my $do = $self->element($tree->descend($node, $name)); $do ? ($nodetype => $do) : (); } -- Regards, MarkOv ------------------------------------------------------------------------ Mark Overmeer MSc MARKOV Solutions Mark@Overmeer.net solutions@overmeer.net http://Mark.Overmeer.net http://solutions.overmeer.net
Am Mi 12. Jun 2013, 18:04:40, secretaris@nluug.nl schrieb: Show quoted text
> In XML/Compile/Schema.pm change
I found the particleElement() method in XML/Compile/Translate.pm, but your change definitely fixes the problem :). Now my server-side happily accepts the call from the client. Thank you very much for your fast response and the patch! Best regards Manfred
resolved in XML::Compile 1.35 (to be released)