From f8ce9529c70feac3d8a32639b0a69d8456774336 Mon Sep 17 00:00:00 2001
From: Alex Reisner <alex@alexreisner.com>
Date: Thu, 26 May 2016 09:44:57 -0400
Subject: [PATCH] Use more consistent cache keys for ESRI lookup.

Intended to fix #1048.
---
 lib/geocoder/lookups/esri.rb   | 21 +++++++++++++++++----
 test/unit/lookups/esri_test.rb | 11 +++++++++++
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/lib/geocoder/lookups/esri.rb b/lib/geocoder/lookups/esri.rb
index c634f1a9..16bf95e0 100644
--- a/lib/geocoder/lookups/esri.rb
+++ b/lib/geocoder/lookups/esri.rb
@@ -10,14 +10,16 @@ module Geocoder::Lookup
     end
 
     def query_url(query)
-      search_keyword = query.reverse_geocode? ? "reverseGeocode" : "find"
-
-      "#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{search_keyword}?" +
-        url_query_string(query)
+      base_query_url(query) + url_query_string(query)
     end
 
     private # ---------------------------------------------------------------
 
+    def base_query_url(query)
+      action = query.reverse_geocode? ? "reverseGeocode" : "find"
+      "#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{action}?"
+    end
+
     def results(query)
       return [] unless doc = fetch_data(query)
 
@@ -32,6 +34,17 @@ module Geocoder::Lookup
       end
     end
 
+    def cache_key(query)
+      base_query_url(query) + hash_to_query(cache_key_params(query))
+    end
+
+    def cache_key_params(query)
+      # omit api_key and token because they may vary among requests
+      query_url_params(query).reject do |key,value|
+        [:api_key, :token].include?(key)
+      end
+    end
+
     def query_url_params(query)
       params = {
         :f => "pjson",
diff --git a/test/unit/lookups/esri_test.rb b/test/unit/lookups/esri_test.rb
index a14ac8a5..a2d2e624 100644
--- a/test/unit/lookups/esri_test.rb
+++ b/test/unit/lookups/esri_test.rb
@@ -110,6 +110,17 @@ class EsriTest < GeocoderTestCase
       result.viewport
   end
 
+  def test_cache_key_doesnt_include_api_key_or_token
+    token = Geocoder::EsriToken.new('xxxxx', Time.now + 60)
+    Geocoder.configure(esri: {token: token, api_key: "xxxxx", for_storage: true})
+    query = Geocoder::Query.new("Bluffton, SC")
+    lookup = Geocoder::Lookup.get(:esri)
+    key = lookup.send(:cache_key, query)
+    assert_match /forStorage/, key
+    assert_no_match /token/, key
+    assert_no_match /api_key/, key
+  end
+
   def teardown
     Geocoder.configure(esri: {token: nil, for_storage: nil})
   end
-- 
GitLab