Zeep with Complex Header

你说的曾经没有我的故事 提交于 2021-01-29 02:03:50

问题


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:

  • What is the correct way to pass parameters to _soapheaders
  • Why is sessionToken not reflected in the header

回答1:


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>



回答2:


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

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


来源:https://stackoverflow.com/questions/62924433/zeep-with-complex-header

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!