diff --git a/lib/opencage/error.rb b/lib/opencage/error.rb new file mode 100644 index 0000000..799a19c --- /dev/null +++ b/lib/opencage/error.rb @@ -0,0 +1,37 @@ +module OpenCage + class Error < StandardError + attr_reader :code + + InvalidRequest = Class.new(self) + AuthenticationError = Class.new(self) + QuotaExceeded = Class.new(self) + Forbidden = Class.new(self) + InvalidEndpoint = Class.new(self) + NotAllowedMethod = Class.new(self) + Timeout = Class.new(self) + RequestTooLong = Class.new(self) + UpgradeRequired = Class.new(self) + TooManyRequests = Class.new(self) + InternalServer = Class.new(self) + + def initialize(message:, code: nil) + super(message) + @code = code + end + + ERRORS = { + 0 => OpenCage::Error, + 400 => OpenCage::Error::InvalidRequest, + 401 => OpenCage::Error::AuthenticationError, + 402 => OpenCage::Error::QuotaExceeded, + 403 => OpenCage::Error::Forbidden, + 404 => OpenCage::Error::InvalidEndpoint, + 405 => OpenCage::Error::NotAllowedMethod, + 408 => OpenCage::Error::Timeout, + 410 => OpenCage::Error::RequestTooLong, + 426 => OpenCage::Error::UpgradeRequired, + 429 => OpenCage::Error::TooManyRequests, + 503 => OpenCage::Error::InternalServer + } + end +end \ No newline at end of file diff --git a/lib/opencage/geocoder.rb b/lib/opencage/geocoder.rb index 1f8b815..22af730 100644 --- a/lib/opencage/geocoder.rb +++ b/lib/opencage/geocoder.rb @@ -1,14 +1,14 @@ require 'opencage/geocoder/location' require 'opencage/geocoder/request' +require 'opencage/error' require 'open-uri' require 'json' module OpenCage class Geocoder - GeocodingError = Class.new(StandardError) def initialize(default_options = {}) - @api_key = default_options.fetch(:api_key) { raise GeocodingError, 'missing API key' } + @api_key = default_options.fetch(:api_key) { raise_error('401 Missing API key') } end def geocode(location, options = {}) @@ -22,7 +22,7 @@ def geocode(location, options = {}) def reverse_geocode(lat, lng, options = {}) if [lat, lng].any? { |coord| !coord.is_a?(Numeric) } - raise GeocodingError, "not valid numeric coordinates: #{lat.inspect}, #{lng.inspect}" + raise_error("400 Not valid numeric coordinates: #{lat.inspect}, #{lng.inspect}") end geocode("#{lat},#{lng}", options).first @@ -33,18 +33,13 @@ def reverse_geocode(lat, lng, options = {}) def fetch(url) JSON.parse(URI(url).open.read)['results'] rescue OpenURI::HTTPError => e - raise GeocodingError, error_message(e) + raise_error(e) end - def error_message(error) - case String(error) - when /^403/ - 'invalid API key' - when /^402/ - 'out of quota' - else - error - end + def raise_error(error) + code = String(error).slice(0, 3) + klass = OpenCage::Error::ERRORS[code.to_i] + raise klass.new(message: String(error), code: code.to_i) end end end diff --git a/spec/cassettes/OpenCage_Geocoder/authentication/raises_an_error_when_geocoding_if_the_API_key_is_incorrect.yml b/spec/cassettes/OpenCage_Geocoder/authentication/raises_an_error_when_geocoding_if_the_API_key_is_incorrect.yml index 56981ed..26174e0 100644 --- a/spec/cassettes/OpenCage_Geocoder/authentication/raises_an_error_when_geocoding_if_the_API_key_is_incorrect.yml +++ b/spec/cassettes/OpenCage_Geocoder/authentication/raises_an_error_when_geocoding_if_the_API_key_is_incorrect.yml @@ -15,27 +15,33 @@ http_interactions: - Ruby response: status: - code: 403 - message: Forbidden + code: 401 + message: Unauthorized headers: Date: - - Sat, 30 Mar 2019 15:11:18 GMT + - Wed, 26 Oct 2022 16:01:21 GMT Server: - - Apache/2.4.29 (Ubuntu) + - Apache Access-Control-Allow-Origin: - "*" - Transfer-Encoding: - - chunked + Vary: + - Accept-Encoding + X-Frame-Options: + - DENY + X-Xss-Protection: + - 1; mode=block + Content-Length: + - '288' Content-Type: - application/json; charset=utf-8 Strict-Transport-Security: - - max-age=31536000; includeSubDomains + - max-age=31536000; includeSubDomains; preload body: - encoding: UTF-8 - string: '{"documentation":"https://opencagedata.com/api","licenses":[{"name":"CC-BY-SA","url":"https://creativecommons.org/licenses/by-sa/3.0/"},{"name":"ODbL","url":"https://opendatacommons.org/licenses/odbl/summary/"}],"results":[],"status":{"code":403,"message":"invalid - API key"},"stay_informed":{"blog":"https://blog.opencagedata.com","twitter":"https://twitter.com/opencagedata"},"thanks":"For - using an OpenCage Data API","timestamp":{"created_http":"Sat, 30 Mar 2019 - 15:11:18 GMT","created_unix":1553958678},"total_results":0}' - http_version: - recorded_at: Sat, 30 Mar 2019 15:11:18 GMT -recorded_with: VCR 4.0.0 + encoding: ASCII-8BIT + string: '{"documentation":"https://opencagedata.com/api","licenses":[{"name":"see + attribution guide","url":"https://opencagedata.com/credits"}],"results":[],"status":{"code":401,"message":"invalid + API key"},"stay_informed":{"blog":"https://blog.opencagedata.com","twitter":"https://twitter.com/OpenCage"},"thanks":"For + using an OpenCage API","timestamp":{"created_http":"Wed, 26 Oct 2022 16:01:20 + GMT","created_unix":1666800080},"total_results":0}' + recorded_at: Wed, 26 Oct 2022 16:01:20 GMT +recorded_with: VCR 6.0.0 diff --git a/spec/geocoder_spec.rb b/spec/geocoder_spec.rb index eaa9617..a2e9a39 100644 --- a/spec/geocoder_spec.rb +++ b/spec/geocoder_spec.rb @@ -9,14 +9,14 @@ def geo it 'raises an error if the API key is missing' do expect do OpenCage::Geocoder.new - end.to raise_error(OpenCage::Geocoder::GeocodingError) + end.to raise_error(OpenCage::Error::AuthenticationError) end it 'raises an error when geocoding if the API key is incorrect', :vcr do expect do geo = OpenCage::Geocoder.new(api_key: 'AN-INVALID-KEY') geo.geocode('SOMEWHERE') - end.to raise_error(OpenCage::Geocoder::GeocodingError, 'invalid API key') + end.to raise_error(OpenCage::Error::AuthenticationError) end it 'raises an error when geocoding if the user is out of quota' do @@ -26,7 +26,7 @@ def geo expect do geo.geocode('SOMEWHERE') - end.to raise_error(OpenCage::Geocoder::GeocodingError, 'out of quota') + end.to raise_error(OpenCage::Error::QuotaExceeded) end end @@ -46,7 +46,7 @@ def geo it 'raises an error for non-numeric input' do expect do geo.reverse_geocode('NOT-A-COORD', 51.50934) - end.to raise_error(OpenCage::Geocoder::GeocodingError, 'not valid numeric coordinates: "NOT-A-COORD", 51.50934') + end.to raise_error(OpenCage::Error::InvalidRequest) end end