From c129780de6f1d8a4b8b6af1dbed63afceb3c9717 Mon Sep 17 00:00:00 2001
From: Olivier Garcia <olivier@lol.cat>
Date: Wed, 27 Apr 2011 18:03:23 +0200
Subject: [PATCH] Geocoder will try to use environment's http_proxy or
 https_proxy when doing lookups unless that behaviour has been disabled in the
 configuration

---
 lib/geocoder/configuration.rb |  3 +++
 lib/geocoder/lookups/base.rb  | 23 +++++++++++++++++++++--
 test/geocoder_test.rb         | 28 ++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/lib/geocoder/configuration.rb b/lib/geocoder/configuration.rb
index 775a4ff3..7ee2776b 100644
--- a/lib/geocoder/configuration.rb
+++ b/lib/geocoder/configuration.rb
@@ -15,6 +15,9 @@ module Geocoder
         # use HTTPS for lookup requests? (if supported)
         [:use_https, false],
 
+        # use Proxy when http_proxy / https_proxy is set in ENV
+        [:use_proxy, true],
+
         # API key for geocoding service
         [:api_key, nil],
 
diff --git a/lib/geocoder/lookups/base.rb b/lib/geocoder/lookups/base.rb
index 3960df8b..d3687f89 100644
--- a/lib/geocoder/lookups/base.rb
+++ b/lib/geocoder/lookups/base.rb
@@ -1,4 +1,6 @@
 require 'net/http'
+require 'uri'
+
 unless defined?(ActiveSupport::JSON)
   begin
     require 'rubygems' # for Ruby 1.8
@@ -52,6 +54,23 @@ module Geocoder
 
       private # -------------------------------------------------------------
 
+      ##
+      # Object used to fetch requests
+      #
+      def http_client
+        proxy_url = ENV[Geocoder::Configuration.use_https ? 'https_proxy' : 'http_proxy']
+        return Net::HTTP unless Geocoder::Configuration.use_proxy && proxy_url
+
+        begin
+          uri = URI.parse(proxy_url)
+        rescue URI::InvalidURIError
+          raise ConfigurationError, "The proxy URL in environment (" +
+            "#{Geocoder::Configuration.use_https ? 'https_proxy' : 'http_proxy'} => #{proxy_url}" +
+            ") was not parsed correctly by URI::Parse"
+        end
+        Net::HTTP::Proxy(uri.host, uri.port, uri.user, uri.password)
+      end
+
       ##
       # Geocoder::Result object or nil on timeout or other error.
       #
@@ -84,7 +103,7 @@ module Geocoder
         rescue TimeoutError
           warn "Geocoding API not responding fast enough " +
             "(see Geocoder::Configuration.timeout to set limit)."
-      end
+        end
       end
 
       ##
@@ -117,7 +136,7 @@ module Geocoder
         timeout(Geocoder::Configuration.timeout) do
           url = query_url(query, reverse)
           unless cache and response = cache[url]
-            response = Net::HTTP.get_response(URI.parse(url)).body
+            response = http_client.get_response(URI.parse(url)).body
             if cache
               cache[url] = response
             end
diff --git a/test/geocoder_test.rb b/test/geocoder_test.rb
index b86b7db4..e3cef93e 100644
--- a/test/geocoder_test.rb
+++ b/test/geocoder_test.rb
@@ -20,6 +20,34 @@ class GeocoderTest < Test::Unit::TestCase
 
   # --- sanity checks ---
 
+  def test_uses_proxy_by_default
+    lookup = Geocoder::Lookup::Base.new
+
+    ENV.delete 'http_proxy'
+    ENV.delete 'https_proxy'
+    assert ! lookup.send(:http_client).proxy_class?
+
+    ENV['http_proxy'] = 'http://localhost'
+    assert_equal 'localhost', lookup.send(:http_client).proxy_address
+
+    Geocoder::Configuration.use_https = true
+    ENV['https_proxy'] = 'https://localhost-ssl'
+    assert_equal 'localhost-ssl', lookup.send(:http_client).proxy_address
+  end
+
+  def test_exception_raised_on_bad_proxy_url
+    ENV['http_proxy'] = ' \\_O< Quack Quack'
+    assert_raise Geocoder::ConfigurationError do
+      Geocoder::Lookup::Base.new.send(:http_client)
+    end
+  end
+
+  def test_uses_direct_connection_when_forced
+    Geocoder::Configuration.use_proxy = false
+    ENV['http_proxy'] = 'http://localhost:8080'
+    assert ! Geocoder::Lookup::Base.new.send(:http_client).proxy_class?
+  end
+
   def test_uses_https_for_secure_query
     Geocoder::Configuration.use_https = true
     g = Geocoder::Lookup::Google.new
-- 
GitLab