go-xml icon indicating copy to clipboard operation
go-xml copied to clipboard

WSDL Response decoding does not seem to work

Open leth opened this issue 6 years ago • 7 comments

I cannot, despite my best efforts, find a way to decode the response body. The envelope is processed fine, just the contents of the Body is not decoded.

I think we need a test case for the generated code, as #25 calls for

leth avatar Jan 02 '19 13:01 leth

I admit I haven't even manually tested this part of the generated code very thoroughly. Would you happen to have a WSDL endpoint in mind that we can use as an example?

droyo avatar Jan 03 '19 06:01 droyo

I'm new to the world of WSDL, so don't have any examples to test against. It's fairly striaghtforward to catch: if you marshal and serialise a request struct to bytes, then try to deserialise and marshal it back to structs then it will just be empty.

IIUC it's because the Envelope Body is an interface{}; go can marshal it since it has a instance to reflect on, but it can't unmarshal it because it's not sure what type they should be.

leth avatar Jan 03 '19 08:01 leth

Ah, it looks like the tests I have in wsdlgen/examples/* only test marshalling.

I think the gentests/_testgen can be easily extended to generate tests for wsdlgen if there is a *.wsdl file, and mock responses if there is a *.sample file in the relevant directory, with some inspiration from the links you gave me in #25.

droyo avatar Jan 03 '19 13:01 droyo

Ok, I 've got some rudimentary tests pushed in the issue-25 branch and I think I might see the problem. It looks like I may have added an unnecessary layer of encapsulation in the temporary types used to marshal/unmarshal requests and responses. Example:

WSDL:

<message name="GetLastTradePriceOutput">
    <part name="body" element="xsd1:TradePrice"/>
</message>

<portType name="StockQuotePortType">
    <operation name="GetLastTradePrice">
       <input message="tns:GetLastTradePriceInput"/>
       <output message="tns:GetLastTradePriceOutput"/>
    </operation>
</portType>

Go:

var output struct {
	XMLName struct{} `xml:"http://example.com/stockquote.wsdl GetLastTradePrice"`
	Args    struct {
		Body TradePrice `xml:"http://example.com/stockquote.wsdl body"`
	} `xml:"http://example.com/stockquote.wsdl GetLastTradePriceOutput"`
}

I'll need to check the soap spec again to see what the correct behavior is here.

droyo avatar Jan 05 '19 18:01 droyo

Ok, the relevant portion of the WSDL spec is https://www.w3.org/TR/2001/NOTE-wsdl-20010315#_porttypes and it does seem like I have a few too many layers here.

droyo avatar Jan 06 '19 08:01 droyo

OK, reading the specs a bit more I'm beginning to understand.

https://www.w3.org/TR/2001/NOTE-wsdl-20010315#_soap:operation

The value of this attribute also affects the way in which the Body of the SOAP message is constructed [...] If the attribute is not specified, it defaults to the value specified in the soap:binding element. If the soap:binding element does not specify a style, it is assumed to be "document".

https://www.w3.org/TR/2001/NOTE-wsdl-20010315#_soap:body

If the operation style is rpc each part is a parameter or a return value and appears inside a wrapper element within the body (following Section 7.1 of the SOAP specification). [...] If the operation style is document there are no additional wrappers, and the message parts appear directly under the SOAP Body element.

Relevant portions of the SOAP spec:

rpc style: https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383533 doc style: https://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383503

So next steps would be:

  • extend wsdl package to parse the soap:binding element (it was ignored prior)
  • extend wsdl package to classify operations as "One-way", "Request-response", "Solicit-response", or "Notification".
  • when using rpc style for an operation or binding, parameters should be members of a wrapper struct.
    • If the relevant part for the parameter is not named, its name is that of the operation, plus ""/"Request"/"Response"/"Solicit", depending on the type of operation.
  • when using document style for an operation or binding, parameters are dropped right into the soap envelope's Body element.

I opened #76 for the related goal of generating error types for soap faults.

droyo avatar Jan 09 '19 05:01 droyo

Thanks for looking into this in such detail! In the interim I've switched to xsdgen, and manually built the soap envelope handling for my service.

I'm working with an operation which binds input and output to the SOAP body:

      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>

leth avatar Jan 09 '19 09:01 leth