google_map_services 0.1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,85 @@
1
+ require 'google_maps_service/convert'
2
+
3
+ module GoogleMapsService::Apis
4
+
5
+ # Performs requests to the Google Maps Geocoding API.
6
+ module Geocoding
7
+
8
+ # Geocoding is the process of converting addresses
9
+ # (like `"1600 Amphitheatre Parkway, Mountain View, CA"`) into geographic
10
+ # coordinates (like latitude 37.423021 and longitude -122.083739), which you
11
+ # can use to place markers or position the map.
12
+ #
13
+ # @example Geocode an address
14
+ # results = client.geocode('Sydney')
15
+ #
16
+ # @example Geocode a component only
17
+ # results = client.geocode(nil, components: {administrative_area: 'TX', country: 'US'})
18
+ #
19
+ # @example Geocode an address and component
20
+ # results = client.geocode('Sydney', components: {administrative_area: 'TX', country: 'US'})
21
+ #
22
+ # @example Multiple parameters
23
+ # results = client.geocode('Sydney',
24
+ # components: {administrative_area: 'TX', country: 'US'},
25
+ # bounds: {
26
+ # northeast: {lat: 32.7183997, lng: -97.26864001970849},
27
+ # southwest: {lat: 32.7052583, lng: -97.27133798029149}
28
+ # },
29
+ # region: 'us')
30
+ #
31
+ # @param [String] address The address to geocode. You must specify either this value and/or `components`.
32
+ # @param [Hash] components A component filter for which you wish to obtain a geocode,
33
+ # for example: `{'administrative_area': 'TX','country': 'US'}`
34
+ # @param [String, Hash] bounds The bounding box of the viewport within which to bias geocode
35
+ # results more prominently. Accept string or hash with `northeast` and `southwest` keys.
36
+ # @param [String] region The region code, specified as a ccTLD (_top-level domain_)
37
+ # two-character value.
38
+ # @param [String] language The language in which to return results.
39
+ #
40
+ # @return [Array] Array of geocoding results.
41
+ def geocode(address, components: nil, bounds: nil, region: nil, language: nil)
42
+ params = {}
43
+
44
+ params[:address] = address if address
45
+ params[:components] = GoogleMapsService::Convert.components(components) if components
46
+ params[:bounds] = GoogleMapsService::Convert.bounds(bounds) if bounds
47
+ params[:region] = region if region
48
+ params[:language] = language if language
49
+
50
+ return get('/maps/api/geocode/json', params)[:results]
51
+ end
52
+
53
+ # Reverse geocoding is the process of converting geographic coordinates into a
54
+ # human-readable address.
55
+ #
56
+ # @example Simple lat/lon pair
57
+ # client.reverse_geocode({lat: 40.714224, lng: -73.961452})
58
+ #
59
+ # @example Multiple parameters
60
+ # client.reverse_geocode([40.714224, -73.961452],
61
+ # location_type: ['ROOFTOP', 'RANGE_INTERPOLATED'],
62
+ # result_type: ['street_address', 'route'],
63
+ # language: 'es')
64
+ #
65
+ # @param [Hash, Array] latlng The latitude/longitude value for which you wish to obtain
66
+ # the closest, human-readable address.
67
+ # @param [String, Array<String>] location_type One or more location types to restrict results to.
68
+ # @param [String, Array<String>] result_type One or more address types to restrict results to.
69
+ # @param [String] language The language in which to return results.
70
+ #
71
+ # @return [Array] Array of reverse geocoding results.
72
+ def reverse_geocode(latlng, location_type: nil, result_type: nil, language: nil)
73
+ params = {
74
+ latlng: GoogleMapsService::Convert.latlng(latlng)
75
+ }
76
+
77
+ params[:result_type] = GoogleMapsService::Convert.join_list('|', result_type) if result_type
78
+ params[:location_type] = GoogleMapsService::Convert.join_list('|', location_type) if location_type
79
+ params[:language] = language if language
80
+
81
+ return get('/maps/api/geocode/json', params)[:results]
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,20 @@
1
+ require 'google_maps_service/convert'
2
+
3
+ module GoogleMapsService::Apis
4
+
5
+ # Performs requests to the Google Maps Geocoding API.
6
+ module Places
7
+ def places_autocomplete(input, components: nil, bounds: nil, types: nil, region: nil, language: nil)
8
+ params = {}
9
+
10
+ params[:input] = input
11
+ params[:components] = GoogleMapsService::Convert.components(components) if components
12
+ params[:bounds] = GoogleMapsService::Convert.bounds(bounds) if bounds
13
+ params[:region] = region if region
14
+ params[:language] = language if language
15
+ params[:types] = types if types
16
+
17
+ return get('/maps/api/place/autocomplete/json', params)[:predictions]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,187 @@
1
+ require 'multi_json'
2
+
3
+ module GoogleMapsService::Apis
4
+
5
+ # Performs requests to the Google Maps Roads API.
6
+ module Roads
7
+
8
+ # Base URL of Google Maps Roads API
9
+ ROADS_BASE_URL = "https://roads.googleapis.com"
10
+
11
+ # Snaps a path to the most likely roads travelled.
12
+ #
13
+ # Takes up to 100 GPS points collected along a route, and returns a similar
14
+ # set of data with the points snapped to the most likely roads the vehicle
15
+ # was traveling along.
16
+ #
17
+ # @example Single point snap
18
+ # results = client.snap_to_roads([40.714728, -73.998672])
19
+ #
20
+ # @example Multi points snap
21
+ # path = [
22
+ # [-33.8671, 151.20714],
23
+ # [-33.86708, 151.20683000000002],
24
+ # [-33.867070000000005, 151.20674000000002],
25
+ # [-33.86703, 151.20625]
26
+ # ]
27
+ # results = client.snap_to_roads(path, interpolate: true)
28
+ #
29
+ # @param [Array] path The path to be snapped. Array of latitude/longitude pairs.
30
+ # @param [Boolean] interpolate Whether to interpolate a path to include all points
31
+ # forming the full road-geometry. When true, additional interpolated
32
+ # points will also be returned, resulting in a path that smoothly
33
+ # follows the geometry of the road, even around corners and through
34
+ # tunnels. Interpolated paths may contain more points than the
35
+ # original path.
36
+ #
37
+ # @return [Array] Array of snapped points.
38
+ def snap_to_roads(path, interpolate: false)
39
+ path = GoogleMapsService::Convert.waypoints(path)
40
+
41
+ params = {
42
+ path: path
43
+ }
44
+
45
+ params[:interpolate] = 'true' if interpolate
46
+
47
+ return get('/v1/snapToRoads', params,
48
+ base_url: ROADS_BASE_URL,
49
+ accepts_client_id: false,
50
+ custom_response_decoder: method(:extract_roads_body))[:snappedPoints]
51
+ end
52
+
53
+ # Returns the posted speed limit (in km/h) for given road segments.
54
+ #
55
+ # @example Multi places snap
56
+ # place_ids = [
57
+ # 'ChIJ0wawjUCuEmsRgfqC5Wd9ARM',
58
+ # 'ChIJ6cs2kkCuEmsRUfqC5Wd9ARM'
59
+ # ]
60
+ # results = client.speed_limits(place_ids)
61
+ #
62
+ # @param [String, Array<String>] place_ids The Place ID of the road segment. Place IDs are returned
63
+ # by the snap_to_roads function. You can pass up to 100 Place IDs.
64
+ #
65
+ # @return [Array] Array of speed limits.
66
+ def speed_limits(place_ids)
67
+ params = GoogleMapsService::Convert.as_list(place_ids).map { |place_id| ['placeId', place_id] }
68
+
69
+ return get('/v1/speedLimits', params,
70
+ base_url: ROADS_BASE_URL,
71
+ accepts_client_id: false,
72
+ custom_response_decoder: method(:extract_roads_body))[:speedLimits]
73
+ end
74
+
75
+ # Returns the posted speed limit (in km/h) for given road segments.
76
+ #
77
+ # The provided points will first be snapped to the most likely roads the
78
+ # vehicle was traveling along.
79
+ #
80
+ # @example Multi points snap
81
+ # path = [
82
+ # [-33.8671, 151.20714],
83
+ # [-33.86708, 151.20683000000002],
84
+ # [-33.867070000000005, 151.20674000000002],
85
+ # [-33.86703, 151.20625]
86
+ # ]
87
+ # results = client.snapped_speed_limits(path)
88
+ #
89
+ # @param [Hash, Array] path The path of points to be snapped. A list of (or single)
90
+ # latitude/longitude tuples.
91
+ #
92
+ # @return [Hash] A hash with both a list of speed limits and a list of the snapped
93
+ # points.
94
+ def snapped_speed_limits(path)
95
+ path = GoogleMapsService::Convert.waypoints(path)
96
+
97
+ params = {
98
+ path: path
99
+ }
100
+
101
+ return get('/v1/speedLimits', params,
102
+ base_url: ROADS_BASE_URL,
103
+ accepts_client_id: false,
104
+ custom_response_decoder: method(:extract_roads_body))
105
+ end
106
+
107
+ # Returns the nearest road segments for provided points.
108
+ # The points passed do not need to be part of a continuous path.
109
+ #
110
+ # @example Single point snap
111
+ # results = client.nearest_roads([40.714728, -73.998672])
112
+ #
113
+ # @example Multi points snap
114
+ # points = [
115
+ # [-33.8671, 151.20714],
116
+ # [-33.86708, 151.20683000000002],
117
+ # [-33.867070000000005, 151.20674000000002],
118
+ # [-33.86703, 151.20625]
119
+ # ]
120
+ # results = client.nearest_roads(points)
121
+ #
122
+ # @param [Array] points The points to be used for nearest road segment lookup. Array of latitude/longitude pairs
123
+ # which do not need to be a part of continuous part.
124
+ # Takes up to 100 independent coordinates, and returns the closest road segment for each point.
125
+ #
126
+ # @return [Array] Array of snapped points.
127
+
128
+ def nearest_roads(points)
129
+ points = GoogleMapsService::Convert.waypoints(points)
130
+
131
+ params = {
132
+ points: points
133
+ }
134
+
135
+ return get('/v1/nearestRoads', params,
136
+ base_url: ROADS_BASE_URL,
137
+ accepts_client_id: false,
138
+ custom_response_decoder: method(:extract_roads_body))[:snappedPoints]
139
+ end
140
+
141
+
142
+
143
+ private
144
+ # Extracts a result from a Roads API HTTP response.
145
+ def extract_roads_body(response)
146
+ begin
147
+ body = MultiJson.load(response.body, :symbolize_keys => true)
148
+ rescue
149
+ unless response.status == 200
150
+ check_response_status(response)
151
+ end
152
+ raise GoogleMapsService::Error::ApiError.new(response), 'Received a malformed response.'
153
+ end
154
+
155
+ check_roads_body_error(response, body)
156
+
157
+ unless response.status == 200
158
+ raise GoogleMapsService::Error::ApiError.new(response)
159
+ end
160
+ return body
161
+ end
162
+
163
+ # Check response body for error status.
164
+ #
165
+ # @param [Faraday::Response] response Response object.
166
+ # @param [Hash] body Response body.
167
+ def check_roads_body_error(response, body)
168
+ error = body[:error]
169
+ return unless error
170
+
171
+ case error[:status]
172
+ when 'INVALID_ARGUMENT'
173
+ if error[:message] == 'The provided API key is invalid.'
174
+ raise GoogleMapsService::Error::RequestDeniedError.new(response), error[:message]
175
+ end
176
+ raise GoogleMapsService::Error::InvalidRequestError.new(response), error[:message]
177
+ when 'PERMISSION_DENIED'
178
+ raise GoogleMapsService::Error::RequestDeniedError.new(response), error[:message]
179
+ when 'RESOURCE_EXHAUSTED'
180
+ raise GoogleMapsService::Error::RateLimitError.new(response), error[:message]
181
+ else
182
+ raise GoogleMapsService::Error::ApiError.new(response), error[:message]
183
+ end
184
+ end
185
+
186
+ end
187
+ end
@@ -0,0 +1,41 @@
1
+ require 'date'
2
+
3
+ module GoogleMapsService::Apis
4
+
5
+ # Performs requests to the Google Maps TimeZone API."""
6
+ module TimeZone
7
+
8
+ # Get time zone for a location on the earth, as well as that location's
9
+ # time offset from UTC.
10
+ #
11
+ # @example Current time zone
12
+ # timezone = client.timezone([39.603481, -119.682251])
13
+ #
14
+ # @example Time zone at certain time
15
+ # timezone = client.timezone([39.603481, -119.682251], timestamp: Time.at(1608))
16
+ #
17
+ # @param [Hash, Array] location The latitude/longitude value representing the location to
18
+ # look up.
19
+ # @param [Integer, DateTime] timestamp Timestamp specifies the desired time as seconds since
20
+ # midnight, January 1, 1970 UTC. The Time Zone API uses the timestamp to
21
+ # determine whether or not Daylight Savings should be applied. Times
22
+ # before 1970 can be expressed as negative values. Optional. Defaults to
23
+ # `Time.now`.
24
+ # @param [String] language The language in which to return results.
25
+ #
26
+ # @return [Hash] Time zone object.
27
+ def timezone(location, timestamp: Time.now, language: nil)
28
+ location = GoogleMapsService::Convert.latlng(location)
29
+ timestamp = GoogleMapsService::Convert.time(timestamp)
30
+
31
+ params = {
32
+ location: location,
33
+ timestamp: timestamp
34
+ }
35
+
36
+ params[:language] = language if language
37
+
38
+ return get('/maps/api/timezone/json', params)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,6 @@
1
+ module GoogleMapsService
2
+
3
+ # Collections of Google Maps Web Services
4
+ module Apis
5
+ end
6
+ end
@@ -0,0 +1,292 @@
1
+ require 'faraday'
2
+ #require 'faraday/retry'
3
+ require 'multi_json'
4
+ require 'thread'
5
+
6
+ require 'google_maps_service/errors'
7
+ require 'google_maps_service/convert'
8
+ require 'google_maps_service/url'
9
+ require 'google_maps_service/apis/directions'
10
+ require 'google_maps_service/apis/distance_matrix'
11
+ require 'google_maps_service/apis/elevation'
12
+ require 'google_maps_service/apis/geocoding'
13
+ require 'google_maps_service/apis/roads'
14
+ require 'google_maps_service/apis/time_zone'
15
+ require 'google_maps_service/apis/places'
16
+
17
+ module GoogleMapsService
18
+
19
+ # Core client functionality, common across all API requests (including performing
20
+ # HTTP requests).
21
+ class Client
22
+ # Default Google Maps Web Service base endpoints
23
+ DEFAULT_BASE_URL = 'https://maps.googleapis.com'
24
+
25
+ # Errors those could be retriable.
26
+ RETRIABLE_ERRORS = [GoogleMapsService::Error::ServerError, GoogleMapsService::Error::RateLimitError]
27
+
28
+ include GoogleMapsService::Apis::Directions
29
+ include GoogleMapsService::Apis::DistanceMatrix
30
+ include GoogleMapsService::Apis::Elevation
31
+ include GoogleMapsService::Apis::Geocoding
32
+ include GoogleMapsService::Apis::Roads
33
+ include GoogleMapsService::Apis::TimeZone
34
+ include GoogleMapsService::Apis::Places
35
+
36
+ # Secret key for accessing Google Maps Web Service.
37
+ # Can be obtained at https://developers.google.com/maps/documentation/geocoding/get-api-key#key.
38
+ # @return [String]
39
+ attr_accessor :key
40
+
41
+ # Client id for using Maps API for Work services.
42
+ # @return [String]
43
+ attr_accessor :client_id
44
+
45
+ # Client secret for using Maps API for Work services.
46
+ # @return [String]
47
+ attr_accessor :client_secret
48
+
49
+ # Timeout across multiple retriable requests, in seconds.
50
+ # @return [Integer]
51
+ attr_accessor :retry_timeout
52
+
53
+ # Number of queries per second permitted.
54
+ # If the rate limit is reached, the client will sleep for
55
+ # the appropriate amount of time before it runs the current query.
56
+ # @return [Integer]
57
+ attr_reader :queries_per_second
58
+
59
+ # Construct Google Maps Web Service API client.
60
+ #
61
+ # You can configure `Hurley::Client` through `request_options` and `ssl_options` parameters.
62
+ # You can also directly get the `Hurley::Client` object via {#client} method.
63
+ #
64
+ # @example Setup API keys
65
+ # gmaps = GoogleMapsService::Client.new(key: 'Add your key here')
66
+ #
67
+ # @example Setup client IDs
68
+ # gmaps = GoogleMapsService::Client.new(
69
+ # client_id: 'Add your client id here',
70
+ # client_secret: 'Add your client secret here'
71
+ # )
72
+ #
73
+ # @example Setup time out and QPS limit
74
+ # gmaps = GoogleMapsService::Client.new(
75
+ # key: 'Add your key here',
76
+ # retry_timeout: 20,
77
+ # queries_per_second: 10
78
+ # )
79
+ #
80
+ # @example Request behind proxy
81
+ # request_options = Hurley::RequestOptions.new
82
+ # request_options.proxy = Hurley::Url.parse 'http://user:password@proxy.example.com:3128'
83
+ #
84
+ # gmaps = GoogleMapsService::Client.new(
85
+ # key: 'Add your key here',
86
+ # request_options: request_options
87
+ # )
88
+ #
89
+ # @example Using Excon and Http Cache
90
+ # require 'hurley-excon' # https://github.com/lostisland/hurley-excon
91
+ # require 'hurley/http_cache' # https://github.com/plataformatec/hurley-http-cache
92
+ #
93
+ # gmaps = GoogleMapsService::Client.new(
94
+ # key: 'Add your key here',
95
+ # connection: Hurley::HttpCache.new(HurleyExcon::Connection.new)
96
+ # )
97
+ #
98
+ # @option options [String] :key Secret key for accessing Google Maps Web Service.
99
+ # Can be obtained at https://developers.google.com/maps/documentation/geocoding/get-api-key#key.
100
+ # @option options [String] :client_id Client id for using Maps API for Work services.
101
+ # @option options [String] :client_secret Client secret for using Maps API for Work services.
102
+ # @option options [Integer] :retry_timeout Timeout across multiple retriable requests, in seconds.
103
+ # @option options [Integer] :queries_per_second Number of queries per second permitted.
104
+ #
105
+ # @option options [Hurley::RequestOptions] :request_options HTTP client request options.
106
+ # See https://github.com/lostisland/hurley/blob/master/lib/hurley/options.rb.
107
+ # @option options [Hurley::SslOptions] :ssl_options HTTP client SSL options.
108
+ # See https://github.com/lostisland/hurley/blob/master/lib/hurley/options.rb.
109
+ # @option options [Object] :connection HTTP client connection.
110
+ # By default, the default Hurley's HTTP client connection (Net::Http) will be used.
111
+ # See https://github.com/lostisland/hurley/blob/master/README.md#connections.
112
+ def initialize(**options)
113
+ [:key, :client_id, :client_secret,
114
+ :retry_timeout, :queries_per_second,
115
+ :request_options, :ssl_options, :connection].each do |key|
116
+ self.instance_variable_set("@#{key}".to_sym, options[key] || GoogleMapsService.instance_variable_get("@#{key}"))
117
+ end
118
+
119
+ initialize_query_tickets
120
+ end
121
+
122
+ # Get the current HTTP client.
123
+ # @return [Faraday::Client]
124
+ def client
125
+ @client ||= new_client
126
+ end
127
+
128
+ protected
129
+
130
+ # Initialize QPS queue. QPS queue is a "tickets" for calling API
131
+ def initialize_query_tickets
132
+ if @queries_per_second
133
+ @qps_queue = SizedQueue.new @queries_per_second
134
+ @queries_per_second.times do
135
+ @qps_queue << 0
136
+ end
137
+ end
138
+ end
139
+
140
+ # Create a new HTTP client.
141
+ # @return [Faraday::Connection]
142
+ def new_client
143
+ client = Faraday.new(DEFAULT_BASE_URL)
144
+ #client.request_options.query_class = Hurley::Query::Flat
145
+ #client.request_options.redirection_limit = 0
146
+ client.headers[:user_agent] = user_agent
147
+
148
+ #client.connection = @connection if @connection
149
+ #@request_options.each_pair {|key, value| client.request_options[key] = value } if @request_options
150
+ #@ssl_options.each_pair {|key, value| client.ssl_options[key] = value } if @ssl_options
151
+
152
+ client
153
+ end
154
+
155
+ # Build the user agent header
156
+ # @return [String]
157
+ def user_agent
158
+ sprintf('google-maps-services-ruby/%s %s',
159
+ GoogleMapsService::VERSION,
160
+ GoogleMapsService::OS_VERSION)
161
+ end
162
+
163
+ # Make API call.
164
+ #
165
+ # @param [String] path Url path.
166
+ # @param [String] params Request parameters.
167
+ # @param [String] base_url Base Google Maps Web Service API endpoint url.
168
+ # @param [Boolean] accepts_client_id Sign the request using API {#keys} instead of {#client_id}.
169
+ # @param [Method] custom_response_decoder Custom method to decode raw API response.
170
+ #
171
+ # @return [Object] Decoded response body.
172
+ def get(path, params, base_url: DEFAULT_BASE_URL, accepts_client_id: true, custom_response_decoder: nil)
173
+ url = base_url + generate_auth_url(path, params, accepts_client_id)
174
+
175
+ #Retriable.retriable timeout: @retry_timeout, on: RETRIABLE_ERRORS do |try|
176
+ #begin
177
+ #request_query_ticket
178
+ response = client.get url
179
+ #ensure
180
+ #release_query_ticket
181
+ #end
182
+
183
+ return custom_response_decoder.call(response) if custom_response_decoder
184
+ decode_response_body(response)
185
+ #end
186
+ end
187
+
188
+ # Get/wait the request "ticket" if QPS is configured.
189
+ # Check for previous request time, it must be more than a second ago before calling new request.
190
+ #
191
+ # @return [void]
192
+ def request_query_ticket
193
+ if @qps_queue
194
+ elapsed_since_earliest = Time.now - @qps_queue.pop
195
+ sleep(1 - elapsed_since_earliest) if elapsed_since_earliest.to_f < 1
196
+ end
197
+ end
198
+
199
+ # Release request "ticket".
200
+ #
201
+ # @return [void]
202
+ def release_query_ticket
203
+ @qps_queue << Time.now if @qps_queue
204
+ end
205
+
206
+ # Returns the path and query string portion of the request URL,
207
+ # first adding any necessary parameters.
208
+ #
209
+ # @param [String] path The path portion of the URL.
210
+ # @param [Hash] params URL parameters.
211
+ # @param [Boolean] accepts_client_id Sign the request using API {#keys} instead of {#client_id}.
212
+ #
213
+ # @return [String]
214
+ def generate_auth_url(path, params, accepts_client_id)
215
+ # Deterministic ordering through sorting by key.
216
+ # Useful for tests, and in the future, any caching.
217
+ if params.kind_of?(Hash)
218
+ params = params.sort
219
+ else
220
+ params = params.dup
221
+ end
222
+
223
+ if accepts_client_id and @client_id and @client_secret
224
+ params << ["client", @client_id]
225
+
226
+ path = [path, GoogleMapsService::Url.urlencode_params(params)].join("?")
227
+ sig = GoogleMapsService::Url.sign_hmac(@client_secret, path)
228
+ return path + "&signature=" + sig
229
+ end
230
+
231
+ if @key
232
+ params << ["key", @key]
233
+ return path + "?" + GoogleMapsService::Url.urlencode_params(params)
234
+ end
235
+
236
+ raise ArgumentError, "Must provide API key for this API. It does not accept enterprise credentials."
237
+ end
238
+
239
+ # Extract and parse body response as hash. Throw an error if there is something wrong with the response.
240
+ #
241
+ # @param [Faraday::Response] response Web API response.
242
+ #
243
+ # @return [Hash] Response body as hash. The hash key will be symbolized.
244
+ def decode_response_body(response)
245
+ check_response_status(response)
246
+ body = MultiJson.load(response.body, :symbolize_keys => true)
247
+ check_body_error(response, body)
248
+ body
249
+ end
250
+
251
+ # Check HTTP response status code. Raise error if the status is not 2xx.
252
+ #
253
+ # @param [Faraday::Response] response Web API response.
254
+ def check_response_status(response)
255
+ case response.status
256
+ when 200..300
257
+ # Do-nothing
258
+ when 301, 302, 303, 307
259
+ raise GoogleMapsService::Error::RedirectError.new(response), sprintf('Redirect to %s', response.headers[:location])
260
+ when 401
261
+ raise GoogleMapsService::Error::ClientError.new(response), 'Unauthorized'
262
+ when 304, 400, 402...500
263
+ raise GoogleMapsService::Error::ClientError.new(response), 'Invalid request'
264
+ when 500..600
265
+ raise GoogleMapsService::Error::ServerError.new(response), 'Server error'
266
+ end
267
+ end
268
+
269
+ # Check response body for error status.
270
+ #
271
+ # @param [Faraday::Response] response Response object.
272
+ # @param [Hash] body Response body.
273
+ #
274
+ # @return [void]
275
+ def check_body_error(response, body)
276
+ case body[:status]
277
+ when 'OK', 'ZERO_RESULTS'
278
+ # Do-nothing
279
+ when 'OVER_QUERY_LIMIT'
280
+ raise GoogleMapsService::Error::RateLimitError.new(response), body[:error_message]
281
+ when 'REQUEST_DENIED'
282
+ raise GoogleMapsService::Error::RequestDeniedError.new(response), body[:error_message]
283
+ when 'INVALID_REQUEST'
284
+ raise GoogleMapsService::Error::InvalidRequestError.new(response), body[:error_message]
285
+ when 'NOT_FOUND'
286
+ raise GoogleMapsService::Error::NotFoundError.new(response), (body[:error_message] || 'ADDRESS NOT FOUND')
287
+ else
288
+ raise GoogleMapsService::Error::ApiError.new(response), body[:error_message]
289
+ end
290
+ end
291
+ end
292
+ end