Search code examples
ruby-on-railsrubysavonproximo

Use HTTP proxy with Savon


I need to access a service with an IP whitelist from Heroku, necessitating the need for an HTTP proxy.

I configured the Proximo add on, and have a proxy url that looks approximately like http://proxy:[email protected]

In Savon, I have tried configuring a proxy like so:

client = Savon.client(wsdl: my_wsdl, proxy: "http://proxy:[email protected]")

But when I make a request:

client.operations

I get a proxy error:

Wasabi::Resolver::HTTPError: Error: 407 for url http://mywsdl
        from /Users/ahamon/.gem/ruby/2.3.0/gems/wasabi3.5.0/lib/wasabi/resolver.rb:45:in `load_from_remote'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/wasabi3.5.0/lib/wasabi/resolver.rb:33:in `resolve'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/wasabi3.5.0/lib/wasabi/document.rb:142:in `xml'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/wasabi-3.5.0/lib/wasabi/document.rb:160:in `parse'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/wasabi-3.5.0/lib/wasabi/document.rb:147:in `parser'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/wasabi-3.5.0/lib/wasabi/document.rb:64:in `soap_actions'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/savon-2.11.1/lib/savon/client.rb:28:in `operations'
        from (irb):7
        from /Users/ahamon/.gem/ruby/2.3.0/gems/railties-4.2.4/lib/rails/commands/console.rb:110:in `start'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/railties-4.2.4/lib/rails/commands/console.rb:9:in `start'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:68:in `console'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
        from /Users/ahamon/.gem/ruby/2.3.0/gems/railties-4.2.4/lib/rails/commands.rb:17:in `<top (required)>'
        from bin/rails:4:in `require'
        from bin/rails:4:in `<main>'

Everything works just fine without the proxy option, though.


Solution

  • I think I found a solution. The inconvenience is to fetch the WSDL manually and to save it into a local file. Eg.

    curl http://www.webservicesx.net/globalweather.asmx?wsdl > globalweather.wsdl
    

    You have to add the following to your client definition

    ...
    secret = Base64.strict_encode64("#{user}:#{password}")
    client = Savon.client(
        wsdl: 'globalweather.wsdl',
        proxy: "http://my-proxy.example.com:8080",
        headers: { "Proxy-Authorization" => "Basic #{secret}" },
        ...
    )
    

    That's basically it. You can also work completely without WSDL by specifiying namespace and endpoint directly.

    Savon uses Wasabi to process the WSDL. It also fetches the document from the server. Wasabi doesn't use the parameters from Savon's client definition. To change it one would have to extend the Wasabi gem.

    A running script can be found here: http://pastebin.com/t8NTuGKK.