0

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 > 
hackerkatt
  • 165
  • 11

1 Answers1

0

I couldn't quite see the relation between the xml object (from Builder::XmlMarkup.new) and params[:xml], but I had a stack level too deep problem and fixed this by using message: xml.target!.

thesuperav
  • 81
  • 1
  • 5