当使用savon进行红宝石肥皂通讯时,为什么将“ wsdl”命名空间插入动作名称中?

问题描述 投票:9回答:4

我正在尝试访问不受控制的SOAP服务。动作之一称为ProcessMessage。我按照该示例进行了操作,并生成了一个SOAP请求,但返回一条错误消息说该操作不存在。我将问题追溯到信封主体的生成方式。

<env:Envelope ... ">
    <env:Header>
        <wsse:Security ... ">
            <wsse:UsernameToken ...">
                <wsse:Username>USER</wsse:Username>
                    <wsse:Nonce>658e702d5feff1777a6c741847239eb5d6d86e48</wsse:Nonce>
                    <wsu:Created>2010-02-18T02:05:25Z</wsu:Created>
                    <wsse:Password ... >password</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </env:Header>
    <env:Body>
        <wsdl:ProcessMessage>
            <payload>
                ......
            </payload>
        </wsdl:ProcessMessage>
    </env:Body>
</env:Envelope>     

ProcessMessage标签应为:

    <ProcessMessage xmlns="http://www.starstandards.org/webservices/2005/10/transport">

这就是示例Java应用程序生成的,它可以正常工作。该标签是我的Ruby应用程序生成的与示例Java应用程序之间的唯一区别。有什么方法可以摆脱该标签前面的"wsdl:"名称空间,并添加类似的属性。除此以外,是否有一种方法可以强制不像身体的其余部分那样仅通过字符串传递来生成动作?

这是我的代码:

require 'rubygems'
require 'savon'
client = Savon::Client.new "https://gmservices.pp.gm.com/ProcessMessage?wsdl"

response = client.process_message! do | soap, wsse |
wsse.username = "USER"
wsse.password = "password"
soap.namespace = "http://www.starstandards.org/webservices/2005/10/transport" #makes no difference
soap.action = "ProcessMessage" #makes no difference
soap.input = "ProcessMessage" #makes no difference

#my body at this point is jsut one big xml string

soap.body = "<payload>...</payload>" 
# putting <ProccessMessage> tag here doesn't help as it just creates a duplicate tag in the body, since Savon keeps interjecting  <wsdl:ProcessMessage> tag.

  end

我尝试过握手,但它不支持HTTPS,令人困惑。我尝试过soap4r,但它比handoap更令人困惑。

ruby soap savon
4个回答
10
投票

您需要将数组传递给soap.input,其第二个元素是包含名称空间详细信息的哈希。

soap.input = [ 
  "ProcessMessage", 
  {"xmlns" => "http://www.starstandards.org/webservices/2005/10/transport"}
]

这应确保您最终将名称空间声明作为main元素的属性。

您可能还会在像这样的元素之前以名称空间声明结尾

<env:Body>
    <wsdl:ProcessMessage xmlns="........." >
        <payload>
            ......
        </payload>
    </wsdl:ProcessMessage>
</env:Body>

但是这对我来说不是问题,这是缺少名称空间属性的问题,而不是元素前面没有名称空间。


7
投票

对于我的Web服务,我需要摆脱Steve解决方案之上的"wsdl"命名空间。

使用Savon 0.9.6测试:

client = Savon::Client.new "https://example.com/webservice/account.asmx?WSDL"
response = client.request "GetAccount" do
  # Gotcha 1: set default namespace for body elements
  soap.input = ["GetAccount", {"xmlns" => "https://example.com/webservice/"}]
  soap.body = {
    "AccountID" => 1234
  }
  # Gotcha 2: get rid of namespace declaration of body elements
  soap.element_form_default = :unqualified
  # Gotcha 3: set SOAPAction different from default
  http.headers["SOAPAction"] = '"https://example.com/webservice/GetAccount"'
end

4
投票

Steve,您看到在ProcessMessage标记前面的wsdl:吗? -我以为那是唯一让我失望的事情,但事实并非如此(顺便说一下,这很难在第160行的Savon lib中的soap.rb中设置)。即使我没有在soap.namespaces中将其随意化-它也很难生成并附加在最终的xml中。我的服务不允许这样做。

虽然生成的xml是有效的xml-但由于我要与之交谈的服务的要求,它还不完整。即:在生成的xml中,>

<?xml version="1.0" encoding="UTF-8"?>

标签丢失了,另外,我需要在标题中添加PayloadManifest,另外我还需要在wsse:标签中添加wsu:created和wsu:expires,但是它们尚未实现,等等,等等。还有一些其他的小怪癖太具体了但是soap具有私有方法= xml_body。同样,to_xml方法中的soap lib正在生成@xml_body之前检查@xml_body是否已设置。因此,我最终稍微修改了肥皂的行为。通过使soap.xml_body =可公开访问。所以我能够做到:

response = client.process_message! do |soap| 
soap.action = "http://www.starstandards.org/webservices/2005/10/transport/operations/ProcessMessage"
soap.xml_body = "MY XML STRING GENERATED ELSEWHERE GOES HERE"
end

终于可以使用!!

我将其建议给rubii-如果此选项可用,它将解决很多罕见的情况-人们可以生成其自定义xml并使用savon lib的其余部分。


0
投票

我花了数小时试图找到摆脱的解决方案:

© www.soinside.com 2019 - 2024. All rights reserved.