rightsized
rightsized

Reputation: 180

Zeep with Complex Header

using zeep 3.4.0

wsdl is looking for the following information in header

    <soapenv:Header>\n        
        <vv:sessionHeader soapenv:mustUnderstand=\"1\">\n
            <vv:sessionToken>\n
                <vv:Token1 xmlns:vv=\"http://www.z.com/zTypes.xsd\">{{Token1Token}}
                </vv:Token1>\n
                <vv:Token2 xmlns:vv=\"http://www.z.com/zTypes.xsd\">{{Token2Token}}
                </vv:Token2>\n
            </vv:sessionToken>\n
        </vv:sessionHeader>\n

I am passing parameters to _soapheaders as follows

    headerQ = xsd.Element('Header',xsd.ComplexType  ([
            xsd.Element('sessionHeader',xsd.ComplexType  ([
                xsd.Element('sessionToken', xsd.ComplexType ([
                    xsd.Element('Token1',xsd.String()),
                    xsd.Element('Token2',xsd.String())
                ]))
            ]))
        ]))

    header_value1 = headerQ({'Token1':Token1T, 'Token2':Token2T} )
    client.set_default_soapheaders(header_value1)

header_value1 looks like this

    {
        'sessionHeader': {
            'Token1': 'abcdef=',
            'Token2': 'ghijkl='
        }
    }

I get the following error:

    line 365, in _serialize_header
    raise ValueError("Invalid value given to _soapheaders")

_serialize_header expects header_value1 to be either a list or a dictionary

isinstance(header_value1,dict) returns False

Questions:

Upvotes: 1

Views: 600

Answers (2)

Doug
Doug

Reputation: 36

Debugging things with Zeep is always a bit of a challenge, but here's a working implementation:

In order to correctly render two elements (Token1 and Token2) you need a xsd:Sequence element:

   headerQ = xsd.Element('Header', xsd.ComplexType([
     xsd.Element('{http://www.z.com/zTypes.xsd}sessionHeader', xsd.ComplexType([
       xsd.Element('{http://www.z.com/zTypes.xsd}sessionToken', xsd.ComplexType(
         xsd.Sequence([
           xsd.Element('{http://www.z.com/zTypes.xsd}Token1', xsd.String()),
           xsd.Element('{http://www.z.com/zTypes.xsd', xsd.String())
          ])))
        ], attributes=[xsd.Attribute('mustUnderstand', xsd.Boolean())
     ]))
   ]))

Providing the QNames instead of raw element names will take care of the namespaces and finally you set the attributes on the sessionToken type definition. If your soap server refuses to accept "true" then you can use an xsd:Integer type, or you can rewrite "true" to "1" using an egress plugin as shown here

Setting the header value works as you tried, although you need to wrap into a list:

header_value1 = headerQ(
  {'mustUnderstand': True,
   'sessionToken': {'Token1': 'Token1T',
                    'Token2': 'Token2T'}
  }
)
client.set_default_soapheaders([header_value1])

This gives the header section:

<Header>
  <ns0:sessionHeader xmlns:ns0="http://www.z.com/zTypes.xsd" mustUnderstand="true">
    <ns0:sessionToken>
      <ns0:Token1>Token1T</ns0:Token1>
      <ns0:Token2>Token2T</ns0:Token2>
    </ns0:sessionToken>
  </ns0:sessionHeader>
</Header>

Upvotes: 2

rightsized
rightsized

Reputation: 180

rather than using the built in method, I got it working with

    header_value1 = {'sessionHeader': {'sessionToken': { \
    'primary': token1, secondary': token2}}}

Upvotes: 0

Related Questions