suds:数组数组的编组不正确

发布于 2024-09-14 16:28:13 字数 3754 浏览 10 评论 0原文

我尝试使用 python 与负载均衡器(Zeus ZXTM)通信:

a = client.factory.create('StringArrayArray')
b = client.factory.create('StringArray')
b.value = ['node01:80',]
a.value = [b,]
client.service.addDrainingNodes(['my pool'], a)

但出现以下错误:

suds.WebFault:服务器引发错误:“/usr/local/zeus/zxtmadmin/lib/perl/Zeus/ZXTM/SOAPBase.pm 第 772 行不是 ARRAY 引用。

模式定义摘录:

    <types>
        <xsd:schema targetNamespace='http://soap.zeus.com/zxtm/1.0/'
            xmlns='http://www.w3.org/2001/XMLSchema'
            xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/'
            xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'>

            <xsd:complexType name="StringArray">
                <xsd:complexContent>
                    <xsd:restriction base='SOAP-ENC:Array'>
                        <xsd:attribute ref='SOAP-ENC:arrayType' wsdl:arrayType='xsd:string[]'/>
                    </xsd:restriction>
                </xsd:complexContent>
            </xsd:complexType>

            <xsd:complexType name="StringArrayArray">
                <xsd:complexContent>
                    <xsd:restriction base='SOAP-ENC:Array'>
                        <xsd:attribute ref='SOAP-ENC:arrayType' wsdl:arrayType='zeusns:StringArray[]'/>
                    </xsd:restriction>
                </xsd:complexContent>
            </xsd:complexType>
        </xsd:schema>
    </types>

    <message name="addDrainingNodesRequest">
        <part name="names" type="zeusns:StringArray" />
        <part name="values" type="zeusns:StringArrayArray" />
    </message>

    <message name="addDrainingNodesResponse"></message>

    <portType name="PoolPort">

        <operation name="addDrainingNodes">
            <documentation>
                Add nodes to the lists of draining nodes, for each of the named pools.
            </documentation>

            <input message="zeusns:addDrainingNodesRequest"/>
            <output message="zeusns:addDrainingNodesResponse"/>
        </operation>
    </portType>
</definitions>

我也尝试过这样的: client.service.addDrainingNodes(['我的池'], [['node01:80']]) 它在 SOAPpy 中有效,但现在在肥皂水中我得到:

suds.WebFault:服务器引发错误:“值不是数组”

SOAPpy 和 suds 发送的内容之间的比较:

SOAPpy(有效):

<ns1:addDrainingNodes xmlns:ns1="http://soap.zeus.com/zxtm/1.0/Pool/" SOAP-ENC:root="1">
    <v1 SOAP-ENC:arrayType="xsd:string[1]" xsi:type="SOAP-ENC:Array">
        <item>my pool</item>
    </v1>
    <v2 SOAP-ENC:arrayType="xsd:list[1]" xsi:type="SOAP-ENC:Array">
        <item SOAP-ENC:arrayType="xsd:string[1]" xsi:type="SOAP-ENC:Array">
            <item>node01:80</item>
        </item>
    </v2>
</ns1:addDrainingNodes>

suds(无效) ):

<ns4:addDrainingNodes>
    <names xsi:type="ns0:StringArray" ns3:arrayType="ns2:string[1]">
        <item xsi:type="ns2:string">my pool</item>
    </names>
    <values xsi:type="ns0:StringArrayArray" ns3:arrayType="ns0:StringArray[1]">
        <item xsi:type="ns2:string">node01:80</item>
    </values>
</ns4:addDrainingNodes>

上下文:

  • 我是 suds 和 Soap 的新手,
  • 只有
  • 使用 python2.6 和 suds 0.3.9
  • 到 ZXTM 负载均衡器的 SOAP 接口,我们曾经使用 ZSI 的 SOAPpy,但在 python 2.6 下使用它时遇到问题

编辑< /strong>:添加了 suds/SOAPpy 有效负载

I try to talk to a load balancer (Zeus ZXTM) with python:

a = client.factory.create('StringArrayArray')
b = client.factory.create('StringArray')
b.value = ['node01:80',]
a.value = [b,]
client.service.addDrainingNodes(['my pool'], a)

But I get the following error:

suds.WebFault: Server raised fault: 'Not an ARRAY reference at /usr/local/zeus/zxtmadmin/lib/perl/Zeus/ZXTM/SOAPBase.pm line 772.

Extract of the schema definition:

    <types>
        <xsd:schema targetNamespace='http://soap.zeus.com/zxtm/1.0/'
            xmlns='http://www.w3.org/2001/XMLSchema'
            xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/'
            xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'>

            <xsd:complexType name="StringArray">
                <xsd:complexContent>
                    <xsd:restriction base='SOAP-ENC:Array'>
                        <xsd:attribute ref='SOAP-ENC:arrayType' wsdl:arrayType='xsd:string[]'/>
                    </xsd:restriction>
                </xsd:complexContent>
            </xsd:complexType>

            <xsd:complexType name="StringArrayArray">
                <xsd:complexContent>
                    <xsd:restriction base='SOAP-ENC:Array'>
                        <xsd:attribute ref='SOAP-ENC:arrayType' wsdl:arrayType='zeusns:StringArray[]'/>
                    </xsd:restriction>
                </xsd:complexContent>
            </xsd:complexType>
        </xsd:schema>
    </types>

    <message name="addDrainingNodesRequest">
        <part name="names" type="zeusns:StringArray" />
        <part name="values" type="zeusns:StringArrayArray" />
    </message>

    <message name="addDrainingNodesResponse"></message>

    <portType name="PoolPort">

        <operation name="addDrainingNodes">
            <documentation>
                Add nodes to the lists of draining nodes, for each of the named pools.
            </documentation>

            <input message="zeusns:addDrainingNodesRequest"/>
            <output message="zeusns:addDrainingNodesResponse"/>
        </operation>
    </portType>
</definitions>

I also tried like this:
client.service.addDrainingNodes(['my pool'], [['node01:80']])
which worked in SOAPpy but now in suds I get:

suds.WebFault: Server raised fault: 'Value isn't an array'

Comparison between what SOAPpy and what suds sends:

SOAPpy (works):

<ns1:addDrainingNodes xmlns:ns1="http://soap.zeus.com/zxtm/1.0/Pool/" SOAP-ENC:root="1">
    <v1 SOAP-ENC:arrayType="xsd:string[1]" xsi:type="SOAP-ENC:Array">
        <item>my pool</item>
    </v1>
    <v2 SOAP-ENC:arrayType="xsd:list[1]" xsi:type="SOAP-ENC:Array">
        <item SOAP-ENC:arrayType="xsd:string[1]" xsi:type="SOAP-ENC:Array">
            <item>node01:80</item>
        </item>
    </v2>
</ns1:addDrainingNodes>

suds (doesn't work):

<ns4:addDrainingNodes>
    <names xsi:type="ns0:StringArray" ns3:arrayType="ns2:string[1]">
        <item xsi:type="ns2:string">my pool</item>
    </names>
    <values xsi:type="ns0:StringArrayArray" ns3:arrayType="ns0:StringArray[1]">
        <item xsi:type="ns2:string">node01:80</item>
    </values>
</ns4:addDrainingNodes>

Context:

  • I'm new to suds and Soap
  • there's only the SOAP interface to the ZXTM loadbalancer
  • using python2.6 and suds 0.3.9
  • we used to use ZSI's SOAPpy, but had issues using it under python 2.6

Edit: Added suds/SOAPpy payloads

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

玉环 2024-09-21 16:28:13

在尝试了

  • 这个函数的无数不同参数
  • 来自 ZSI 的 wsdl2py

之后,我发现 suds 4.0 提供了插件,可以通过黑客解决这个问题,但尽管如此,我认为这是一个 suds 错误:

class FixArrayPlugin(Plugin):
    def sending(self, context):
        command = context.envelope.getChild('Body').getChildren()[0].name
        if command == 'addDrainingNodes':
            context.envelope.addPrefix('xsd', 'http://www.w3.org/1999/XMLSchema')
            values = context.envelope.getChild('Body').getChild('addDrainingNodes').getChild('values')
            values.set('SOAP-ENC:arrayType', 'xsd:list[1]')
            values.set('xsi:type', 'SOAP-ENC:Array')
            item = values[0]
            item.set('SOAP-ENC:arrayType', 'xsd:list[1]')
            item.set('xsi:type', 'SOAP-ENC:Array')

client = Client(wsdl, location=location, plugins=[FixArrayPlugin()])
a = client.factory.create('StringArrayArray')
b = client.factory.create('StringArray')
b.item = ['node01:80']
a.item = [b,]
client.service.addDrainingNodes(['my pool'], a)

我期待着这个问题得到修复,IMO这应该是单行
我保留这个开放性,因为我仍然对更好的替代方案感兴趣

After trying

  • zillions of different arguments to this function
  • wsdl2py from ZSI

I found out that suds 4.0 offers plugins, that solves this case by hacking, but nonetheless I think that's a suds bug:

class FixArrayPlugin(Plugin):
    def sending(self, context):
        command = context.envelope.getChild('Body').getChildren()[0].name
        if command == 'addDrainingNodes':
            context.envelope.addPrefix('xsd', 'http://www.w3.org/1999/XMLSchema')
            values = context.envelope.getChild('Body').getChild('addDrainingNodes').getChild('values')
            values.set('SOAP-ENC:arrayType', 'xsd:list[1]')
            values.set('xsi:type', 'SOAP-ENC:Array')
            item = values[0]
            item.set('SOAP-ENC:arrayType', 'xsd:list[1]')
            item.set('xsi:type', 'SOAP-ENC:Array')

client = Client(wsdl, location=location, plugins=[FixArrayPlugin()])
a = client.factory.create('StringArrayArray')
b = client.factory.create('StringArray')
b.item = ['node01:80']
a.item = [b,]
client.service.addDrainingNodes(['my pool'], a)

I'm looking forward for this issue to be fixed, IMO this should be a one liner
I'm leaving this open as I'm still interested in better alternatives

孤芳又自赏 2024-09-21 16:28:13

在我看来奇怪的是,您必须显式构造“StringArrayArray”和“StringArray”等类型 - 使用 Python 等语言的足够智能的 SOAP 客户端应该能够通过反射来解决这个问题,检查您传递给服务调用的参数。我猜它们在 wsdl 中被声明为类似“SOAP-ENC:Array”的东西 - 如果是这样,它们就不打算成为对象。这对于错误消息“不是数组引用”也是有意义的。你有没有尝试过;

a = [ ['node01:80',], ]
client.service.addDrainingNodes(['my pool'], a)

或者失败了……祝

a = client.factory.create('StringArrayArray')
b = ['node01:80',]
a.value = [ b, ]
client.service.addDrainingNodes(['my pool'], a)

你好运。

What looks strange to me is you have to explicitly construct types like 'StringArrayArray' and 'StringArray' - a smart enough SOAP client in a language like python should be able to figure this out via reflection, examining the arguments you pass to the service call. I'm guessing they're declared in the wsdl as something like "SOAP-ENC:Array" - if so they're not intended to be objects. That would also make sense with the error message "Not an ARRAY reference". Have you tried just;

a = [ ['node01:80',], ]
client.service.addDrainingNodes(['my pool'], a)

Or failing that perhaps...

a = client.factory.create('StringArrayArray')
b = ['node01:80',]
a.value = [ b, ]
client.service.addDrainingNodes(['my pool'], a)

Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文