python - 使用 suds 在 SOAP 请求中多次发送相同类型

标签 python web-services soap wsdl suds

我正在使用 suds python 库编写一个 SOAP 客户端。我正在使用的服务不提供 WSDL 文件,所以我必须手写一个。我正在尝试发出一个请求,该请求接受可变数量的类型作为参数。

目前,我在 WSDL 中有以下方法:

  <wsdl:message name="get_usertagRequest">
    <wsdl:part name="email" type="xsd:string"
               minOccurs="1" maxOccurs="1"/>
    <wsdl:part name="tag" type="xsd:string"
               minOccurs="0" maxOccurs="unbounded"/>
  </wsdl:message>

我可以通过以下代码使用单个标记参数调用它:

client = Client(url)
service = client.service['debian.org']
foo = service.get_usertag('someone@debian.org', tag='malloc')

这会产生一个如下所示的请求:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns3="urn:Debbugs/SOAP" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns4="urn:Debbugs/SOAP/TYPES" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Header/>
   <ns0:Body>
      <ns3:get_usertag>
         <email xsi:type="ns1:string">someone@debian.org</email>
         <tag xsi:type="ns4:string">malloc</tag>
      </ns3:get_usertag>
   </ns0:Body>
</SOAP-ENV:Envelope>

如何修改我的代码或 WSDL 以生成如下所示的请求?

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns3="urn:Debbugs/SOAP" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns4="urn:Debbugs/SOAP/TYPES" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Header/>
   <ns0:Body>
      <ns3:get_usertag>
         <email xsi:type="ns1:string">someone@debian.org</email>
         <tag xsi:type="ns4:string">malloc</tag>
         <tag xsi:type="ns4:string">anothertag</tag>
      </ns3:get_usertag>
   </ns0:Body>
</SOAP-ENV:Envelope>

更新的尝试

我根据以下 Herry 的回答尝试了新方法。将他的建议直接插入到 wsdl 会导致解析 wsdl 失败:

<xsd:schema targetNamespace="ns6:your_namespace" attributeFormDefault="qualified" elementFormDefault="qualified">
    <xsd:element name="tag_list">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element maxOccurs="unbounded" minOccurs="0" name="tag" nillable="true" type="ns4:string" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

Suds 抛出异常:Exception: prefix (ns6) not resolved

我尝试将 elementcomplexType 定义添加到我现有的类型命名空间中:

  <wsdl:types>
    <schema targetNamespace="urn:Debbugs/SOAP/TYPES"
        xmlns="http://www.w3.org/2001/XMLSchema">
      <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
       <element name="tag_list">
         <complexType>
           <sequence>
             <element maxOccurs="unbounded" minOccurs="0" name="tag" nillable="true" type="xsd:string" />
           </sequence>
         </complexType>
       </element>

--截图--

  <wsdl:message name="get_usertagRequest">
    <wsdl:part name="email" type="xsd:string"
               minOccurs="1" maxOccurs="1"/>
    <wsdl:part name="tag" element="types:tag_list"
               minOccurs="0" maxOccurs="unbounded"/>

这导致了以下请求:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns3="urn:Debbugs/SOAP" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns4="urn:Debbugs/SOAP/TYPES" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Header/>
   <ns0:Body>
      <ns3:get_usertag>
         <email xsi:type="ns1:string">someone@debian.org</email>
         <tag_list xsi:type="ns4:tag_list">malloc</tag_list>
      </ns3:get_usertag>
   </ns0:Body>
</SOAP-ENV:Envelope>

由于它改变了类型,服务器返回了一个错误:

suds.WebFault: Server raised fault: 'Application failed during request deserialization: Unrecognized type '{urn:Debbugs/SOAP/TYPES}tag_list'

即使没有错误,我也无法让 suds 发送相同的标签两次。使用更新的 wsdl:

# only malloc is sent in the request
foo = service.get_usertag('someone@debian.org', 'malloc', 'foo')

# results in suds.TypeNotFound: Type not found: 'tag_list'
foo = service.get_usertag('someone@debian.org', ['malloc', 'foo'])

可以找到我目前正在使用的完整 wsdl here .

最佳答案

根据您的评论,我已经开始调查服务器端不处理数组的原因。我已经检查了您的 SOAP.pm 中的代码。我只关注 get_usertag 方法,它处理或将处理一个或三个参数:

 my %ut = get_usertag('don@donarmstrong.com','this-bug-sucks','eat-this-bug');
 my %ut = get_usertag('don@donarmstrong.com');

我认为您的目标是提出一个接受可变数量类型作为参数的请求。之前,我建议您在参数中使用一种复合类型(complexType),它具有多个或零个参数。

现在我检查 SOAP::Lite documentation它说:

  • No support for multidimensional, partially transmitted and sparse arrays (however arrays of arrays are supported, as well as any other data structures, and you can add your own implementation with SOAP::Data).
  • Limited support for WSDL schema.

因此,支持简单数组和 SOAP::Data。从技术上讲,可以发送和处理数组(第二个限制对我来说是个坏消息)。但我可以想象不支持数组的另一个原因(另一个客户端使用这种方法......)。请同时检查 differences between a SOAP::WSDL and SOAP::Lite .

我想过很多选项如何发送很多参数,但是对于每个选项都需要更改服务器端代码。也许你可以做一些 hack/magic 来解决这个问题(使用一个包含所有参数并在服务器端拆分的参数),但我认为简单 SOAP::Data是更好的选择。

我没有更改 WSDL 结构。您可以使用我的波纹管代码。请在get_usertag方法中更改服务器端代码(我以前没有见过perl代码,我不会写这段代码)。该方法声明了两个字段 $email@tags。请更改为 $email$tag_list$tag_list 包含 @tags 数组。


基于您的 WSDL,我简单地创建了 WSDL。它只包含两个操作,消息和一个模式。这个 shema 使用你的命名空间。所以它不需要指定另一个命名空间。以下是 WSDL 的相关部分:

<wsdl:types>

    <xsd:schema  targetNamespace="urn:Debbugs/SOAP" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">

    <xsd:element name="get_usertagResponse" >
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="msg" minOccurs="0" maxOccurs="unbounded"  type="xsd:string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
<!--The new Tag_lis element-->
      <xsd:element name="Tag_list" >
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="tag" minOccurs="0" maxOccurs="unbounded"  type="xsd:string" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>

  </wsdl:types>
<!--get_usertagRequest use Tag_lis element-->
  <wsdl:message name="get_usertagRequest">
    <wsdl:part name="email" type="xsd:string"/>
    <wsdl:part name="tag_list" element="tns:Tag_list"/>
  </wsdl:message>

  <wsdl:message name="get_usertagResponse">
    <wsdl:part name="msg" type="tns:get_usertagResponse"/>
  </wsdl:message>

我认为您可以将这部分实现到您的 WSDL 中。如果可能,请合并模式。这段代码有效,我在 soapUi 中对其进行了测试。我收到以下请求:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="urn:Debbugs/SOAP">
   <soapenv:Header/>
   <soapenv:Body>
      <soap:get_usertag soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <email xsi:type="xsd:string">?</email>
         <soap:Tag_list>
            <!--Zero or more repetitions:-->
            <tag xsi:type="xsd:string">?</tag>
         </soap:Tag_list>
      </soap:get_usertag>
   </soapenv:Body>
</soapenv:Envelope>

在这种情况下,客户端发送这些参数:

client = Client(url)
service = client.service['debian.org']
foo = service.get_usertag('someone@debian.org', tag_list=['malloc', 'amother'])

关于python - 使用 suds 在 SOAP 请求中多次发送相同类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21071589/

相关文章:

java - 从 JAX-WS 上的 SOAPMessage 获取方法签名名称

python - 如何对目录中的所有文件运行单元测试?

python - 如何创建递归函数将多级字典对象打印到文件

android - 有没有更好的方法在 Android 中解析 SoapObject

java - 休息网络服务

javascript - 使用 npm 请求向 SOAP api 发送帖子

python - 用数字和字符串数据存储字典

python - 运行时错误 : could not open display

iphone - 如何在 ios 中将 sendSynchronousRequest 更改为 sendASynchronousRequest?

java - CXF Web 服务服务器将请求凭证委托(delegate)给内部 Web 服务调用