1.1.0 から Savon v2.0.2 にアップグレードしたところ、アプリが壊れてしまいました。エラー コールバック (Savon::SOAP::Fault から Savon::SOAPFault、Savon::HTTP::Error から Savon::HTTPError など) の変更を考慮して、コードに必要な調整を行い、# call と #request メソッド。スタック レベルが深すぎるため、エラーの追跡に問題がありますエラー。ulimit -s を 40000 まで増やしましたが、何の助けにもなりません。v2より前のコードは問題なく動作するため、コードのループであるとは思いません。Savon サイトのどこにでも、または Google 検索の結果として示されている例はどれも、API を提供するアプライアンスに対して行う必要がある (そして行った) XML 呼び出しに近いものではありません。これは、作成する必要があるクライアント構成、XML 構造体、ビルダー、および XML 要求に対して私が持っているものです。アップグレード前の作業バージョンのコードも含めます。どんな方向性でも大歓迎です。セキュリティのために、IP、ドメインなどを隠しています。追加情報が必要な場合はお知らせください。
ありがとうございました!
td
両方のバージョンに共通:
@api = api.capitalize
service_api_host = '10.10.10.1'
url = "https://#{service_api_host}:8443/#{api}/#{api}?wsdl"
@uname = 'username'
@pwd = 'password'
@xml1 = "xmlns:soapenv"
@xml2 = "xmlns:ws"
@xmlns1 = "http://schemas.xmlsoap.org/soap/envelope/"
@xmlns2 = "http://ws.#{@api.downcase}.myappliances_domain.com"
典型的な XML リクエスト:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.reportingservices.myappliances_domain.com">
<soapenv:Header xmlns:svsec="http://services.myappliances_domain.com">
<svsec:username>username</svsec:username>
<svsec:password>password</svsec:password>
</soapenv:Header>
<soapenv:Body>
<ws:RunTimeSeriesReportRequest>
<ReportDefinition>MyReportDefinition</ReportDefinition>
<CsvAttachmentFormat>
<Compression>None</Compression>
<Encoding>UTF-8</Encoding>
<Headers>true</Headers>
</CsvAttachmentFormat>
<TimeSeriesReportQuery>
<QueryFields>
<QueryField>PeriodStart</QueryField>
<QueryField>PeriodEnd</QueryField>
<QueryField>Subscriber.Name</QueryField>
<QueryField>TotalReceivedBytes</QueryField>
<QueryField>TotalTransmittedBytes</QueryField>
<QueryField>TotalBytes</QueryField>
</QueryFields>
<QueryFilters>
<QueryFilter>
<QueryField>Subscriber.Name</QueryField>
<Criteria>Equal</Criteria>
<Value>078DF7</Value>
</QueryFilter>
</QueryFilters>
<MaxRows>0</MaxRows>
<QueryLocalDataHomeOnly>false</QueryLocalDataHomeOnly>
<TimeSeries>
<Start>2012-12-19T06:00:00-07:00</Start>
<End>2012-12-20T00:00:00-07:00</End>
<TimeZone>America/Phoenix</TimeZone>
<Interval>
<Unit>Hours</Unit>
<Value>18</Value>
</Interval>
</TimeSeries>
</TimeSeriesReportQuery>
</ws:RunTimeSeriesReportRequest>
</soapenv:Body>
</soapenv:Envelope>
完全を期すために:(ユニークなリクエストを作成する多くのビルダーの1つ)
xml = Builder::XmlMarkup.new( :indent=>2 )
xml.soapenv:Envelope, :"#{@xml1}"=>"#{@xmlns1}", :"#{@xml2}"=>"#{@xmlns2}" do
xml.tag!( 'soapenv:Header', :'xmlns:svsec' => 'http://services.myappliances_domain.com' ) do
xml.tag!( 'svsec:username', @uname )
xml.tag!( 'svsec:password', @pwd )
end
xml.tag!( 'soapenv:Body' ) do
xml.tag!( "ws:#{request}" ) do
xml.ReportDefinition('MyReportDefinition')
xml.CsvAttachmentFormat do
xml.Compression('None')
xml.Encoding('UTF-8')
xml.Headers('true')
end
xml.TimeSeriesReportQuery do
xml.QueryFields do
xml.QueryField('PeriodStart')
xml.QueryField('PeriodEnd')
xml.QueryField('Subscriber.Name')
xml.QueryField('TotalReceivedBytes')
xml.QueryField('TotalTransmittedBytes')
xml.QueryField('TotalBytes')
end
xml.QueryFilters do
xml.QueryFilter do
xml.QueryField('Subscriber.Name')
xml.Criteria('Equal')
xml.Value(sub)
end
end
xml.MaxRows(0)
xml.QueryLocalDataHomeOnly('false')
xml.TimeSeries do
xml.Start("#{start_date}")
xml.End("#{end_date}")
xml.TimeZone('America/Phoenix')
xml.Interval do
xml.Unit('Hours')
xml.Value('18')
end
end
end
end
end
end
アップグレード前:
クライアント定義
@client = Savon::Client.new do |wsdl, http|
wsdl.document = url
http.auth.ssl.verify_mode = :none
http.read_timeout = 120
end
通話をリクエスト
@response = @client.request "#{params[:reqMethod]}" do
soap.xml = "#{params[:xml]}"
end
アップグレード後:
クライアント定義
@client = Savon.client(wsdl: url,
encoding: "UTF-8",
soap_version: 2,
ssl_verify_mode: :none,
open_timeout: 5,
read_timeout: 120)
通話をリクエスト
response = @client.call(:"#{params[:reqMethod]}", xml: params[:xml])
アップデート
Builder の結果を返す典型的なメソッドを次に示します。オブジェクトではなく文字列です。
Rails コンソールから:
ruby-1.9.3-p0 :020 > @uname = 'username'
=> "username"
ruby-1.9.3-p0 :021 > @pwd = 'password'
=> "password"
ruby-1.9.3-p0 :022 > api = 'SubscriberServices'
=> "SubscriberServices"
ruby-1.9.3-p0 :023 > @api = api.capitalize
=> "Subscriberservices"
ruby-1.9.3-p0 :024 > @xml1 = "xmlns:soapenv"
=> "xmlns:soapenv"
ruby-1.9.3-p0 :025 > @xml2 = "xmlns:ws"
=> "xmlns:ws"
ruby-1.9.3-p0 :026 > @xmlns1 = "http://schemas.xmlsoap.org/soap/envelope/"
=> "http://schemas.xmlsoap.org/soap/envelope/"
ruby-1.9.3-p0 :027 > @xmlns2 = "http://ws.#{@api.downcase}.myappliance_domain.com"
=> "http://ws.subscriberservices.myappliance_domain.com"
ruby-1.9.3-p0 :028 > def getSubAttributes(subscriber)
ruby-1.9.3-p0 :029?> request = 'LookupSubscriberRequest'
ruby-1.9.3-p0 :030?>
ruby-1.9.3-p0 :031 > xml = Builder::XmlMarkup.new( :indent=>2 )
ruby-1.9.3-p0 :032?> xml.soapenv:Envelope, :"#{@xml1}"=>"#{@xmlns1}", :"#{@xml2}"=>"#{@xmlns2}" do
ruby-1.9.3-p0 :033 > xml.tag!( 'soapenv:Header', :'xmlns:svsec' => 'http://services.myappliance_domain.com' ) do
ruby-1.9.3-p0 :034 > xml.tag!( 'svsec:username', @uname )
ruby-1.9.3-p0 :035?> xml.tag!( 'svsec:password', @pwd )
ruby-1.9.3-p0 :036?> end
ruby-1.9.3-p0 :037?> xml.tag!( 'soapenv:Body' ) do
ruby-1.9.3-p0 :038 > xml.tag!( "ws:#{request}" ) do
ruby-1.9.3-p0 :039 > xml.SubscriberKey() do
ruby-1.9.3-p0 :040 > xml.SubscriberRealmKey() do
ruby-1.9.3-p0 :041 > xml.Name('DEFAULT')
ruby-1.9.3-p0 :042?> end
ruby-1.9.3-p0 :043?> xml.Name(subscriber)
ruby-1.9.3-p0 :044?> end
ruby-1.9.3-p0 :045?> xml.ResponseGroups() do
ruby-1.9.3-p0 :046 > xml.ResponseGroup('Subscriber.Attributes')
ruby-1.9.3-p0 :047?> xml.ResponseGroup('Subscriber.CurrentIpAssignments')
ruby-1.9.3-p0 :048?> end
ruby-1.9.3-p0 :049?> end
ruby-1.9.3-p0 :050?> end
ruby-1.9.3-p0 :051?> end
ruby-1.9.3-p0 :052?> end
=> nil
ruby-1.9.3-p0 :053 > x = getSubAttributes('3C754A70BDE3')
=> "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.subscriberservices.myappliance_domain.com\">\n <soapenv:Header xmlns:svsec=\"http://services.myappliance_domain.com\">\n <svsec:username>username</svsec:username>\n <svsec:password>password</svsec:password>\n </soapenv:Header>\n <soapenv:Body>\n <ws:LookupSubscriberRequest>\n <SubscriberKey>\n <SubscriberRealmKey>\n <Name>DEFAULT</Name>\n </SubscriberRealmKey>\n <Name>3C754A70BDE3</Name>\n </SubscriberKey>\n <ResponseGroups>\n <ResponseGroup>Subscriber.Attributes</ResponseGroup>\n <ResponseGroup>Subscriber.CurrentIpAssignments</ResponseGroup>\n </ResponseGroups>\n </ws:LookupSubscriberRequest>\n </soapenv:Body>\n</soapenv:Envelope>\n"
ruby-1.9.3-p0 :054 > x.class
=> String
ruby-1.9.3-p0 :055 > x.target!
NoMethodError: undefined method `target!' for #<String:0x0000000497a348>
from (irb):55
from /usr/local/rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.9/lib/rails/commands/console.rb:47:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.9/lib/rails/commands/console.rb:8:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.9/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
ruby-1.9.3-p0 :056 >
更新 2
xml Builder オブジェクトを明示的に返さない場合は、文字列を取得します。
api = 'SubscriberServices'
@api = api.capitalize
@uname = 'username'
@pwd = 'password'
@xml1 = "xmlns:soapenv"
@xml2 = "xmlns:ws"
@xmlns1 = "http://schemas.xmlsoap.org/soap/envelope/"
@xmlns2 = "http://ws.#{@api.downcase}.myappliance_domain.com"
def getSubAttributes(subscriber)
request = 'LookupSubscriberRequest'
xml = Builder::XmlMarkup.new( :indent=>2 )
xml.soapenv:Envelope, :"#{@xml1}"=>"#{@xmlns1}", :"#{@xml2}"=>"#{@xmlns2}" do
xml.tag!( 'soapenv:Header', :'xmlns:svsec' => 'http://services.myappliance_domain.com' ) do
xml.tag!( 'svsec:username', @uname )
xml.tag!( 'svsec:password', @pwd )
end
xml.tag!( 'soapenv:Body' ) do
xml.tag!( "ws:#{request}" ) do
xml.SubscriberKey() do
xml.SubscriberRealmKey() do
xml.Name('DEFAULT')
end
xml.Name(subscriber)
end
xml.ResponseGroups() do
xml.ResponseGroup('Subscriber.Attributes')
xml.ResponseGroup('Subscriber.CurrentIpAssignments')
end
end
end
end
return xml
end
テスト中...
ruby-1.9.3-p0 :294 > api = 'SubscriberServices'
=> "SubscriberServices"
ruby-1.9.3-p0 :295 > @api = api.capitalize
=> "Subscriberservices"
ruby-1.9.3-p0 :296 > @uname = 'username'
=> "username"
ruby-1.9.3-p0 :297 > @pwd = 'password'
=> "password"
ruby-1.9.3-p0 :298 >
ruby-1.9.3-p0 :299 > @xml1 = "xmlns:soapenv"
=> "xmlns:soapenv"
ruby-1.9.3-p0 :300 > @xml2 = "xmlns:ws"
=> "xmlns:ws"
ruby-1.9.3-p0 :301 > @xmlns1 = "http://schemas.xmlsoap.org/soap/envelope/"
=> "http://schemas.xmlsoap.org/soap/envelope/"
ruby-1.9.3-p0 :302 > @xmlns2 = "http://ws.#{@api.downcase}.myappliance_domain.com"
=> "http://ws.subscriberservices.myappliance_domain.com"
ruby-1.9.3-p0 :303 >
ruby-1.9.3-p0 :304 > def getSubAttributes(subscriber)
ruby-1.9.3-p0 :305?> request = 'LookupSubscriberRequest'
ruby-1.9.3-p0 :306?>
ruby-1.9.3-p0 :307 > xml = Builder::XmlMarkup.new( :indent=>2 )
ruby-1.9.3-p0 :308?> xml.soapenv:Envelope, :"#{@xml1}"=>"#{@xmlns1}", :"#{@xml2}"=>"#{@xmlns2}" do
ruby-1.9.3-p0 :309 > xml.tag!( 'soapenv:Header', :'xmlns:svsec' => 'http://services.myappliance_domain.com' ) do
ruby-1.9.3-p0 :310 > xml.tag!( 'svsec:username', @uname )
ruby-1.9.3-p0 :311?> xml.tag!( 'svsec:password', @pwd )
ruby-1.9.3-p0 :312?> end
ruby-1.9.3-p0 :313?> xml.tag!( 'soapenv:Body' ) do
ruby-1.9.3-p0 :314 > xml.tag!( "ws:#{request}" ) do
ruby-1.9.3-p0 :315 > xml.SubscriberKey() do
ruby-1.9.3-p0 :316 > xml.SubscriberRealmKey() do
ruby-1.9.3-p0 :317 > xml.Name('DEFAULT')
ruby-1.9.3-p0 :318?> end
ruby-1.9.3-p0 :319?> xml.Name(subscriber)
ruby-1.9.3-p0 :320?> end
ruby-1.9.3-p0 :321?> xml.ResponseGroups() do
ruby-1.9.3-p0 :322 > xml.ResponseGroup('Subscriber.Attributes')
ruby-1.9.3-p0 :323?> xml.ResponseGroup('Subscriber.CurrentIpAssignments')
ruby-1.9.3-p0 :324?> end
ruby-1.9.3-p0 :325?> end
ruby-1.9.3-p0 :326?> end
ruby-1.9.3-p0 :327?> end
ruby-1.9.3-p0 :328?>
Display all 540 possibilities? (y or n)
ruby-1.9.3-p0 :328?> xml
ruby-1.9.3-p0 :329?> end
=> nil
ruby-1.9.3-p0 :330 > x = getSubAttributes('3C754A70BDE3')
=> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.subscriberservices.myappliance_domain.com">
<soapenv:Header xmlns:svsec="http://services.myappliance_domain.com">
<svsec:username>username</svsec:username>
<svsec:password>password</svsec:password>
</soapenv:Header>
<soapenv:Body>
<ws:LookupSubscriberRequest>
<SubscriberKey>
<SubscriberRealmKey>
<Name>DEFAULT</Name>
</SubscriberRealmKey>
<Name>3C754A70BDE3</Name>
</SubscriberKey>
<ResponseGroups>
<ResponseGroup>Subscriber.Attributes</ResponseGroup>
<ResponseGroup>Subscriber.CurrentIpAssignments</ResponseGroup>
</ResponseGroups>
</ws:LookupSubscriberRequest>
</soapenv:Body>
</soapenv:Envelope>
<inspect/>
ruby-1.9.3-p0 :331 > x.class
=> "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.subscriberservices.myappliance_domain.com\">\n <soapenv:Header xmlns:svsec=\"http://services.myappliance_domain.com\">\n <svsec:username>username</svsec:username>\n <svsec:password>password</svsec:password>\n </soapenv:Header>\n <soapenv:Body>\n <ws:LookupSubscriberRequest>\n <SubscriberKey>\n <SubscriberRealmKey>\n <Name>DEFAULT</Name>\n </SubscriberRealmKey>\n <Name>3C754A70BDE3</Name>\n </SubscriberKey>\n <ResponseGroups>\n <ResponseGroup>Subscriber.Attributes</ResponseGroup>\n <ResponseGroup>Subscriber.CurrentIpAssignments</ResponseGroup>\n </ResponseGroups>\n </ws:LookupSubscriberRequest>\n </soapenv:Body>\n</soapenv:Envelope>\n<inspect/>\n<class/>\n"
ruby-1.9.3-p0 :332 > s = x.to_xml
=> "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.subscriberservices.myappliance_domain.com\">\n <soapenv:Header xmlns:svsec=\"http://services.myappliance_domain.com\">\n <svsec:username>username</svsec:username>\n <svsec:password>password</svsec:password>\n </soapenv:Header>\n <soapenv:Body>\n <ws:LookupSubscriberRequest>\n <SubscriberKey>\n <SubscriberRealmKey>\n <Name>DEFAULT</Name>\n </SubscriberRealmKey>\n <Name>3C754A70BDE3</Name>\n </SubscriberKey>\n <ResponseGroups>\n <ResponseGroup>Subscriber.Attributes</ResponseGroup>\n <ResponseGroup>Subscriber.CurrentIpAssignments</ResponseGroup>\n </ResponseGroups>\n </ws:LookupSubscriberRequest>\n </soapenv:Body>\n</soapenv:Envelope>\n<inspect/>\n<class/>\n<to_xml/>\n"
ruby-1.9.3-p0 :333 > s.class
=> String
ruby-1.9.3-p0 :334 >