From 8ea26463e23e35e1e3f07ea395db06115c73437a Mon Sep 17 00:00:00 2001 From: Rafael Petry Date: Wed, 3 Apr 2019 18:17:50 -0400 Subject: [PATCH] Escape special characters in Google API components filter. --- ...nent_filtering_with_special_characters.yml | 126 ++++++++++++++++++ lib/geokit/geocoders/google.rb | 3 +- test/test_google_geocoder.rb | 11 +- 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 fixtures/vcr_cassettes/test_component_filtering_with_special_characters.yml diff --git a/fixtures/vcr_cassettes/test_component_filtering_with_special_characters.yml b/fixtures/vcr_cassettes/test_component_filtering_with_special_characters.yml new file mode 100644 index 00000000..a4709105 --- /dev/null +++ b/fixtures/vcr_cassettes/test_component_filtering_with_special_characters.yml @@ -0,0 +1,126 @@ +--- +http_interactions: +- request: + method: get + uri: https://maps.google.com/maps/api/geocode/json?address=S%C3%A3o%20Paulo&components=administrative_area:s%C3%A3o%20paulo%7Ccountry:br&sensor=false + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - application/json; charset=UTF-8 + Date: + - Wed, 03 Apr 2019 22:15:01 GMT + Pragma: + - no-cache + Expires: + - Fri, 01 Jan 1990 00:00:00 GMT + Cache-Control: + - no-cache, must-revalidate + Vary: + - Accept-Language + Access-Control-Allow-Origin: + - "*" + Server: + - mafe + X-Xss-Protection: + - '0' + X-Frame-Options: + - SAMEORIGIN + Server-Timing: + - gfet4t7; dur=1 + Alt-Svc: + - quic=":443"; ma=2592000; v="46,44,43,39" + Transfer-Encoding: + - chunked + body: + encoding: UTF-8 + string: | + { + "results": [ + { + "address_components": [ + { + "long_name": "São Paulo", + "short_name": "São Paulo", + "types": [ + "locality", + "political" + ] + }, + { + "long_name": "São Paulo", + "short_name": "São Paulo", + "types": [ + "administrative_area_level_2", + "political" + ] + }, + { + "long_name": "State of São Paulo", + "short_name": "SP", + "types": [ + "administrative_area_level_1", + "political" + ] + }, + { + "long_name": "Brazil", + "short_name": "BR", + "types": [ + "country", + "political" + ] + } + ], + "formatted_address": "São Paulo, State of São Paulo, Brazil", + "geometry": { + "bounds": { + "northeast": { + "lat": -23.3566039, + "lng": -46.3650844 + }, + "southwest": { + "lat": -24.0082209, + "lng": -46.825514 + } + }, + "location": { + "lat": -23.5505199, + "lng": -46.63330939999999 + }, + "location_type": "APPROXIMATE", + "viewport": { + "northeast": { + "lat": -23.3566039, + "lng": -46.3650844 + }, + "southwest": { + "lat": -24.0082209, + "lng": -46.825514 + } + } + }, + "place_id": "ChIJ0WGkg4FEzpQRrlsz_whLqZs", + "types": [ + "locality", + "political" + ] + } + ], + "status": "OK" + } + http_version: + recorded_at: Wed, 03 Apr 2019 22:15:01 GMT +recorded_with: VCR 4.0.0 diff --git a/lib/geokit/geocoders/google.rb b/lib/geokit/geocoders/google.rb index 620f60c0..f094f1f0 100644 --- a/lib/geokit/geocoders/google.rb +++ b/lib/geokit/geocoders/google.rb @@ -108,7 +108,8 @@ def self.construct_bias_string_from_options(bias) def self.construct_components_string_from_options(components={}) unless components.empty? - "&components=#{components.to_a.map { |pair| pair.join(':').downcase }.join(CGI.escape('|'))}" + escaped_components = Geokit::Inflector.url_escape(components.to_a.map { |pair| pair.join(":").downcase }.join("|")) + "&components=#{escaped_components}" end end diff --git a/test/test_google_geocoder.rb b/test/test_google_geocoder.rb index ca9d8f6b..54526f4d 100644 --- a/test/test_google_geocoder.rb +++ b/test/test_google_geocoder.rb @@ -353,7 +353,7 @@ def test_component_filtering assert_equal 'TX', filtered_result.state assert_equal 'Austin, TX, USA', filtered_result.full_address - url = 'https://maps.google.com/maps/api/geocode/json?sensor=false&address=austin&components=administrative_area:il%7Ccountry:us' + url = "https://maps.google.com/maps/api/geocode/json?sensor=false&address=austin&components=administrative_area%3Ail%7Ccountry%3Aus" TestHelper.expects(:last_url).with(url) filtered_result = geocode('austin', :test_component_filtering_on, @@ -368,5 +368,14 @@ def test_component_filtering assert_equal 'TX', filtered_result.state assert_equal 'Austin, TX, USA', filtered_result.full_address + + url = "https://maps.google.com/maps/api/geocode/json?sensor=false&address=S%C3%A3o+Paulo&components=administrative_area%3As%C3%A3o+paulo%7Ccountry%3Abr" + TestHelper.expects(:last_url).with(url) + filtered_result = geocode("São Paulo", + :test_component_filtering_with_special_characters, + components: { administrative_area: "São Paulo", country: "BR" }) + + assert_equal "SP", filtered_result.state + assert_equal "São Paulo, State of São Paulo, Brazil", filtered_result.full_address end end