From 4dc3b36e054b328ba2b15bcda3db239c6e9c72c6 Mon Sep 17 00:00:00 2001
From: German Velasco <germsvel@gmail.com>
Date: Tue, 16 Jan 2018 16:03:50 -0500
Subject: [PATCH] Raise bing errors for statuses 403, 500, 503

Bing returns the status codes within the json response. When a request is
forbidden, it will return a 403. If there is an internal server error,
it will return a 500. And if the service is unavailable for some other
reason, it will return a 503. That information was obtained from bing's
[Status Codes and Error
Handling](https://msdn.microsoft.com/en-us/library/ff701703.aspx)
documentation.

We handle those three status codes here to raise
`Geocoder::RequestDenied` (for 403) and `Geocoder::ServiceUnavailable`
(for 500 and 503). This allows for the users of the Geocoder to handle
those errors in their applications.
---
 lib/geocoder/lookups/bing.rb             |  5 +++++
 test/fixtures/bing_forbidden_request     | 16 ++++++++++++++++
 test/fixtures/bing_internal_server_error | 16 ++++++++++++++++
 test/unit/lookups/bing_test.rb           | 14 ++++++++++++++
 4 files changed, 51 insertions(+)
 create mode 100644 test/fixtures/bing_forbidden_request
 create mode 100644 test/fixtures/bing_internal_server_error

diff --git a/lib/geocoder/lookups/bing.rb b/lib/geocoder/lookups/bing.rb
index 53aaadf5..5d46f3a8 100644
--- a/lib/geocoder/lookups/bing.rb
+++ b/lib/geocoder/lookups/bing.rb
@@ -44,6 +44,11 @@ module Geocoder::Lookup
         return doc['resourceSets'].first['estimatedTotal'] > 0 ? doc['resourceSets'].first['resources'] : []
       elsif doc['statusCode'] == 401 and doc["authenticationResultCode"] == "InvalidCredentials"
         raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Bing API key.")
+      elsif doc['statusCode'] == 403
+        raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Bing Geocoding API error: Forbidden Request")
+      elsif [500, 503].include?(doc['statusCode'])
+        raise_error(Geocoder::ServiceUnavailable) ||
+          Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
       else
         Geocoder.log(:warn, "Bing Geocoding API error: #{doc['statusCode']} (#{doc['statusDescription']}).")
       end
diff --git a/test/fixtures/bing_forbidden_request b/test/fixtures/bing_forbidden_request
new file mode 100644
index 00000000..6736e6ab
--- /dev/null
+++ b/test/fixtures/bing_forbidden_request
@@ -0,0 +1,16 @@
+{
+   "authenticationResultCode":"ValidCredentials",
+   "brandLogoUri":"http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
+   "copyright":"Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
+   "resourceSets":[
+      {
+         "estimatedTotal":0,
+         "resources":[
+
+         ]
+      }
+   ],
+   "statusCode":403,
+   "statusDescription":"OK",
+   "traceId":"907b76a307bc49129a489de3d4c992ea|CH1M001463|02.00.82.2800|CH1MSNVM001383, CH1MSNVM001358, CH1MSNVM001397"
+}
diff --git a/test/fixtures/bing_internal_server_error b/test/fixtures/bing_internal_server_error
new file mode 100644
index 00000000..8abd2c4d
--- /dev/null
+++ b/test/fixtures/bing_internal_server_error
@@ -0,0 +1,16 @@
+{
+   "authenticationResultCode":"ValidCredentials",
+   "brandLogoUri":"http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
+   "copyright":"Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
+   "resourceSets":[
+      {
+         "estimatedTotal":0,
+         "resources":[
+
+         ]
+      }
+   ],
+   "statusCode":500,
+   "statusDescription":"OK",
+   "traceId":"907b76a307bc49129a489de3d4c992ea|CH1M001463|02.00.82.2800|CH1MSNVM001383, CH1MSNVM001358, CH1MSNVM001397"
+}
diff --git a/test/unit/lookups/bing_test.rb b/test/unit/lookups/bing_test.rb
index db9457b9..028f8410 100644
--- a/test/unit/lookups/bing_test.rb
+++ b/test/unit/lookups/bing_test.rb
@@ -82,4 +82,18 @@ class BingTest < GeocoderTestCase
       l.send(:results, Geocoder::Query.new("service unavailable"))
     end
   end
+
+  def test_raises_exception_when_bing_returns_forbidden_request
+    Geocoder.configure(:always_raise => [Geocoder::RequestDenied])
+    assert_raises Geocoder::RequestDenied do
+      Geocoder.search("forbidden request")
+    end
+  end
+
+  def test_raises_exception_when_bing_returns_internal_server_error
+    Geocoder.configure(:always_raise => [Geocoder::ServiceUnavailable])
+    assert_raises Geocoder::ServiceUnavailable do
+      Geocoder.search("internal server error")
+    end
+  end
 end
-- 
GitLab