Почему пространство имен "wsdl" вставляется в имя действия при использовании savon для связи с ruby ​​мылом? - PullRequest
8 голосов
/ 19 февраля 2010

Я пытаюсь получить доступ к службе 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, но это еще более запутанно, чем ручное мыло.

Ответы [ 3 ]

10 голосов
/ 16 марта 2010

Вам нужно передать массив в soap.input, вторым элементом которого является хеш, содержащий сведения о пространстве имен.

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

Это должно гарантировать, что вы в конечном итоге объявите пространство имен как атрибут основного элемента.

Вы, вероятно, также получите декларацию пространства имен перед элементом вроде

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

но это не было проблемой для меня, проблема заключалась в отсутствии атрибута пространства имен, а не в наличии пространства имен перед элементом.

7 голосов
/ 07 августа 2011

Для моего веб-сервиса мне нужно было избавиться от пространства имен "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 голосов
/ 16 марта 2010

Стив, вы видите, что wsdl: перед тегом ProcessMessage? - Я думал, что это единственное, что меня отталкивает, но это не так (кстати, это трудно установить в soap.rb в Savon lib на строке 160). Это, даже если я не spacify это в soap.namespaces - это трудно генерируется и прикрепляется в окончательном XML. Что не разрешено моим сервисом.

Хотя генерируемый xml является действительным xml, он не завершен требованиями службы, с которой я пытаюсь поговорить. Т.е .: в сгенерированном xml,

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

тег отсутствует, также мне нужен PayloadManifest в заголовке, плюс мне нужно wsu: созданный и wsu: expires в моем теге wsse:, но они не реализованы, и т. Д., И т. Д. Куча других маленьких причуд, которые слишком специфичны для моего случая. Однако у мыла есть приватный метод = xml_body. Кроме того, мыльная библиотека lib в методе to_xml проверяет, был ли @xml_body уже установлен, прежде чем генерировать свой собственный xml. В итоге я немного изменил поведение мыла. сделав 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.

...