4

Savon Ruby Gem が失敗する SOAP API 呼び出しを生成するという問題に遭遇しましたが、まったく同じ XML メッセージをコピーして SOAP-UI に貼り付けると成功します。

私はこのメッセージを送ります:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tem="http://tempuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:vis="http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts">
<soapenv:Body>
  <tem:CameraConfiguration>
  <tem:request>
   <vis:ClientToken>5555</vis:ClientToken>
   <vis:DeviceID>26219</vis:DeviceID>
    <vis:Enabled>1</vis:Enabled>
    <vis:Interval>60</vis:Interval>
  </tem:request>
 </tem:CameraConfiguration>
</soapenv:Body>

この API へ (リモート Web カメラ構成): https://oapqa.onasset.com/Services/SecureOriginCommand.svc?wsdl

しかし、次のメッセージで失敗します。

 SOAP response (status 500):
 <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
 <s:Body>
 <s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</faultcode>
<faultstring xml:lang="en-US">The message with Action 'oapSetSentryReportingIntervalRequest' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)</faultstring>
 </s:Fault>
</s:Body>

最初に考えたのは、アクション名をタイプミスしたに違いないということでした。しかし、いいえ、SOAP-UI でまったく同じメッセージを試すと、次の成功が得られます。

  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
  <CameraConfigurationResponse xmlns="http://tempuri.org/">
     <CameraConfigurationResult xmlns:a="http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:Error/>
        <a:Result>true</a:Result>
     </CameraConfigurationResult>
  </CameraConfigurationResponse>
 </s:Body>
</s:Envelope>

これにより、問題の原因は xml メッセージの形式ではなく、クライアントの構成方法にあると思われます。実際のコードは次のとおりです。

Savon.configure do |config|
 config.log = :debug
 config.env_namespace = :soapenv
 config.raise_errors = false
end

# TODO Enable ssl certficate verification
client = Savon::Client.new do
  wsdl.document = TARGET_SO_WSDL
  http.auth.ssl.verify_mode = :none
end

resp = client.request 'tem', 'CameraConfiguration' do
  soap.namespaces['xmlns:vis'] = 'http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts'
  soap.namespaces['xmlns:tem'] = 'http://tempuri.org/'
  soap.body = {
    'tem:request' => {
      'vis:ClientToken' => ON_ASSET_API_KEY,
      'vis:DeviceID' => webcam.gps_device.device_id,
      'vis:Enabled' => 1, 
      'vis:Interval' => webcam.report_interval
    }
  }
end

アクセスしようとしている API を管理している開発者と話をしました。彼の答えが手がかりになると思いました:

Binding on the RemoteSentryService was set to mexHttpBinding instead of mexHttpsBinding.


I don’t think this should give you a fault exception, because its working  on .NET simulator client I have. And this endpoint is only used to generate the wsdl (MetaExchange Binding). But, given you are using a different client, I would still give it a shot.

I also regenerated the proxy from wsdl and updated my sample simulator and it looks good.

この問題は、Savon および Microsoft SOAP エンドポイントまたは HTTPS の既知の問題ですか? それとも、この問題は私だけが遭遇したものですか?

4

1 に答える 1

5

それをデバッグし、Savonが残念ながら正しいSOAPActionHTTPヘッダーを送信しないことに気づきました。参考:soapUIを介してSOAPリクエストを送信した後、[RAW]タブ(リクエストウィンドウに垂直に配置されている)をクリックして、さらに調査することができます。

完全な例は次のとおりです。

client = Savon::Client.new do
  wsdl.document = TARGET_SO_WSDL
  http.auth.ssl.verify_mode = :none
end

resp = client.request 'tem', 'CameraConfiguration' do
  # Notice, that the SOAPAction needs to the wrapped in double quotes:
  http.headers['SOAPAction'] = %("http://tempuri.org/ISecureOriginCommand/CameraConfiguration")
  soap.namespaces['xmlns:vis'] = 'http://schemas.datacontract.org/2004/07/Vision.SecureOriginCommand.ServiceContracts'
  soap.body = {
    'tem:request' => {
      'vis:ClientToken' => 5555,
      'vis:DeviceID' => 26219,
      'vis:Enabled' => 1, 
      'vis:Interval' => 60
    }
  }
end

それがあなたのために働くことを願っています!

于 2012-01-26T09:31:08.020 に答える