I upgraded to Savon v2.0.2 from 1.1.0 and it broke my app. I made the necessary adjustments to the code to account for the changes in the Error callbacks (Savon::SOAP::Fault to Savon::SOAPFault, Savon::HTTP::Error to Savon::HTTPError, etc) and using the #call vs the #request method. I'm having trouble tracing the error as now I get a stack level too deep error. I've increased my ulimit -s to as much as 40000 and no help. I don't believe it to be a loop in my code as prior to v2 the code work flawlessly. None of the examples presented anywhere on the Savon site or as a result of a Google search come close to the XML calls I have to make (and have made) to the appliance serving the APIs. Here's what I have for a my client config, XML structs, Builder, and XML Request that has to be made. I'll also include the code from my working version prior to the upgrade. Any direction would be greatly appreciated. For security I've obscured IP's, domains, etc. Please let me know you you need additional information.
Thank you again!
td
Common to both versions:
@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"
Typical XML Request:
<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>
For completeness: (One of a number of Builders to create Unique Requests)
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
Prior to upgrade:
Client def
@client = Savon::Client.new do |wsdl, http|
wsdl.document = url
http.auth.ssl.verify_mode = :none
http.read_timeout = 120
end
Request call
@response = @client.request "#{params[:reqMethod]}" do
soap.xml = "#{params[:xml]}"
end
After upgrade:
Client def
@client = Savon.client(wsdl: url,
encoding: "UTF-8",
soap_version: 2,
ssl_verify_mode: :none,
open_timeout: 5,
read_timeout: 120)
Request call
response = @client.call(:"#{params[:reqMethod]}", xml: params[:xml])
Update
Here's typical method that returns an Builder result. It's a string, not an object.
From the rails console:
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 >
Update 2
If I don't explicitly return the xml Builder object, I get a string.
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
Testing...
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 >