bubbles-rest-client 0.3.1 → 0.7.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.
@@ -10,7 +10,7 @@ module Bubbles
10
10
  ##
11
11
  # Configure the Bubbles instance.
12
12
  #
13
- # Use this method if you want to configure the Bubbles instance, typically during intialization of your Gem or
13
+ # Use this method if you want to configure the Bubbles instance, typically during initialization of your Gem or
14
14
  # application.
15
15
  #
16
16
  # @example In app/config/initializers/bubbles.rb
@@ -39,42 +39,85 @@ module Bubbles
39
39
  #
40
40
  class Configuration
41
41
  def initialize
42
- @environment_scheme = 'http'
43
- @environment_host = '127.0.0.1'
44
- @environment_port = '1234'
45
- @environment_api_key = nil
46
-
42
+ @environments = Hash.new
47
43
  @endpoints = Hash.new
48
44
  end
49
45
 
50
46
  ##
51
- # Retrieve the {RestEnvironment} object defined as part of this Configuration.
47
+ # Retrieve the {RestEnvironment} object defined as part of this Configuration having a specified name.
48
+ #
49
+ # @param [String] environment_name The name of the {RestEnvironment} to retrieve.
50
+ #
51
+ # The +environment_name+ is +nil+ by default, which will return the default configuration, if only one exists.
52
52
  #
53
- # Note that this constructs a new +RestEnvironment+ and returns it, rather than returning an existing object.
53
+ # @return [RestEnvironment] A new +RestEnvironment+ having the configuration that was created with key
54
+ # +environment_name+. Note that +RestEnvironment+s are essentially immutable once they are created, so
55
+ # an existing object will _never_ be returned.
54
56
  #
55
- def environment
56
- RestEnvironment.new(@environment_scheme, @environment_host, @environment_port, @environment_api_key)
57
+ def environment(environment_name = nil)
58
+ if environment_name.nil?
59
+ if @environments.length > 1
60
+ raise 'You must specify an environment_name parameter because more than one environment is defined'
61
+ end
62
+
63
+ env_hash = @environments[nil]
64
+ else
65
+ env_hash = @environments[environment_name]
66
+ end
67
+
68
+ if env_hash.nil?
69
+ if environment_name.nil?
70
+ raise 'No default environment specified'
71
+ end
72
+
73
+ raise 'No environment specified having name {}', environment_name
74
+ end
75
+
76
+ RestEnvironment.new(env_hash[:scheme], env_hash[:host], env_hash[:port], env_hash[:api_key],
77
+ env_hash[:api_key_name])
57
78
  end
58
79
 
59
80
  ##
60
- # Set the current environment.
81
+ # Set the environments that can be used.
61
82
  #
62
- # @param [Object] env The environment, as a generic Ruby Object.
83
+ # @param [Array] environments The environments, as an array with each entry a +Hash+.
84
+ #
85
+ # One or more environments may be specified, but if more than one environment is specified, it is required that each
86
+ # environment have a +:environment_name:+ parameter to differentiate it from other environments.
63
87
  #
64
88
  # @example In app/config/environments/staging.rb:
65
89
  # Bubbles.configure do |config|
66
- # config.environment = {
90
+ # config.environments = [{
67
91
  # :scheme => 'https',
68
92
  # :host => 'stage.api.somehost.com',
69
- # :port => '443'
70
- # }
93
+ # :port => '443',
94
+ # :api_key => 'something',
95
+ # :api_key_name => 'X-API-Key' # Optional
96
+ # }]
71
97
  # end
72
98
  #
73
- def environment=(env)
74
- @environment_scheme = env[:scheme]
75
- @environment_host = env[:host]
76
- @environment_port = env[:port]
77
- @environment_api_key = env[:api_key]
99
+ def environments=(environments)
100
+ default = nil
101
+ environments.each do |environment|
102
+ if environments.length > 1 && environment[:environment_name].nil?
103
+ message = 'More than one environment was specified and at least one of the environments does not have an ' \
104
+ ':environment_name field. Verify all environments have an :environment_name.'
105
+
106
+ raise message
107
+ end
108
+
109
+ @environments = {}
110
+ env_api_key = 'X-API-Key'
111
+ env_api_key = environment[:api_key_name] if environment.key? :api_key_name
112
+
113
+ @environments[environment[:environment_name]] = {
114
+ scheme: environment[:scheme],
115
+ host: environment[:host],
116
+ port: environment[:port],
117
+ api_key: environment[:api_key],
118
+ api_key_name: env_api_key
119
+ }
120
+ end
78
121
  end
79
122
 
80
123
  ##
@@ -103,7 +146,7 @@ module Bubbles
103
146
  def endpoints=(endpoints)
104
147
  new_endpoints = Hash.new
105
148
  endpoints.each do |ep|
106
- endpoint_object = Endpoint.new ep[:method], ep[:location].to_s, ep[:authenticated], ep[:api_key_required], ep[:name], ep[:return_type], ep[:encode_authorization]
149
+ endpoint_object = Endpoint.new ep[:method], ep[:location].to_s, ep[:authenticated], ep[:api_key_required], ep[:name], ep[:return_type], ep[:encode_authorization], ep[:headers]
107
150
 
108
151
  new_endpoints[endpoint_object.get_key_string] = endpoint_object
109
152
  end
@@ -128,99 +171,113 @@ module Bubbles
128
171
  if endpoint.authenticated?
129
172
  Bubbles::RestEnvironment.class_exec do
130
173
  if endpoint.has_uri_params?
131
- define_method(endpoint_name_as_sym) do |auth_token, uri_params|
132
- RestClientResources.execute_get_authenticated self, endpoint, auth_token, uri_params
174
+ if endpoint.encode_authorization_header?
175
+ define_method(endpoint_name_as_sym) do |username, password, uri_params|
176
+ login_data = {
177
+ :login => username,
178
+ :password => password
179
+ }
180
+ auth_value = RestClientResources.get_encoded_authorization(endpoint, login_data)
181
+ RestClientResources.execute_get_authenticated self, endpoint, :basic, auth_value, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
182
+ end
183
+ else
184
+ define_method(endpoint_name_as_sym) do |auth_token, uri_params|
185
+ RestClientResources.execute_get_authenticated self, endpoint, :bearer, auth_token, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
186
+ end
133
187
  end
134
188
  else
135
- define_method(endpoint_name_as_sym) do |auth_token|
136
- RestClientResources.execute_get_authenticated self, endpoint, auth_token, {}
189
+ if endpoint.encode_authorization_header?
190
+ define_method(endpoint_name_as_sym) do |username, password|
191
+ login_data = {
192
+ :username => username,
193
+ :password => password
194
+ }
195
+ auth_value = RestClientResources.get_encoded_authorization(endpoint, login_data)
196
+
197
+ RestClientResources.execute_get_authenticated self, endpoint, :basic, auth_value, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
198
+ end
199
+ else
200
+ define_method(endpoint_name_as_sym) do |auth_token|
201
+ RestClientResources.execute_get_authenticated self, endpoint, :bearer, auth_token, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
202
+ end
137
203
  end
138
204
  end
139
205
  end
140
206
  else
141
207
  Bubbles::RestEnvironment.class_exec do
142
- define_method(endpoint_name_as_sym) do
143
- RestClientResources.execute_get_unauthenticated self, endpoint
208
+ if endpoint.has_uri_params?
209
+ define_method(endpoint_name_as_sym) do |uri_params|
210
+ RestClientResources.execute_get_unauthenticated self, endpoint, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
211
+ end
212
+ else
213
+ define_method(endpoint_name_as_sym) do
214
+ RestClientResources.execute_get_unauthenticated self, endpoint, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
215
+ end
144
216
  end
145
217
  end
146
218
  end
147
219
  elsif endpoint.method == :post
148
- if endpoint.authenticated?
220
+ if endpoint.authenticated? and !endpoint.encode_authorization_header?
149
221
  Bubbles::RestEnvironment.class_exec do
150
222
  define_method(endpoint_name_as_sym) do |auth_token, data|
151
- RestClientResources.execute_post_authenticated self, endpoint, auth_token, data
223
+ RestClientResources.execute_post_authenticated self, endpoint, :bearer, auth_token, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
152
224
  end
153
225
  end
154
- else
155
- if endpoint.api_key_required?
156
- Bubbles::RestEnvironment.class_exec do
157
- define_method(endpoint_name_as_sym) do |data|
158
- additional_headers = {}
159
- if endpoint.encode_authorization_header?
160
- count = 0
161
- auth_value = ''
162
- endpoint.encode_authorization.each { |auth_key|
163
- if data[auth_key]
164
- if count > 0
165
- auth_value = auth_value + ':' + data[auth_key]
166
- else
167
- auth_value = data[auth_key]
168
- end
169
-
170
- count = count + 1
171
-
172
- data.delete(auth_key)
173
- end
174
- }
175
-
176
- additional_headers[:Authorization] = 'Basic ' + Base64.strict_encode64(auth_value)
177
- end
226
+ elsif endpoint.encode_authorization_header?
227
+ Bubbles::RestEnvironment.class_exec do
228
+ define_method(endpoint_name_as_sym) do |username, password, data = {}|
229
+ login_data = {
230
+ :username => username,
231
+ :password => password
232
+ }
178
233
 
179
- RestClientResources.execute_post_with_api_key self, endpoint, self.api_key, data, additional_headers
180
- end
234
+ auth_value = RestClientResources.get_encoded_authorization(endpoint, login_data)
235
+ # composite_headers = RestClientResources.build_composite_headers(endpoint.additional_headers, {
236
+ # Authorization: 'Basic ' + Base64.strict_encode64(auth_value)
237
+ # })
238
+ RestClientResources.execute_post_authenticated self, endpoint, :basic, auth_value, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
239
+ end
240
+ end
241
+ else
242
+ Bubbles::RestEnvironment.class_exec do
243
+ define_method(endpoint_name_as_sym) do |data|
244
+ composite_headers = endpoint.additional_headers
245
+ RestClientResources.execute_post_unauthenticated self, endpoint, data, composite_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
181
246
  end
182
- else
183
- raise 'Unauthenticated POST requests without an API key are not allowed'
184
247
  end
185
248
  end
186
249
  elsif endpoint.method == :delete
187
- if endpoint.authenticated?
188
- Bubbles::RestEnvironment.class_exec do
189
- if endpoint.has_uri_params?
250
+ if endpoint.has_uri_params?
251
+ if endpoint.authenticated?
252
+ Bubbles::RestEnvironment.class_exec do
190
253
  define_method(endpoint_name_as_sym) do |auth_token, uri_params|
191
- RestClientResources.execute_delete_authenticated self, endpoint, auth_token, uri_params
254
+ RestClientResources.execute_delete_authenticated self, endpoint, auth_token, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
255
+ end
256
+ end
257
+ else
258
+ Bubbles::RestEnvironment.class_exec do
259
+ define_method(endpoint_name_as_sym) do |uri_params|
260
+ RestClientResources.execute_delete_unauthenticated self, endpoint, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
192
261
  end
193
- else
194
- # NOTE: While MDN states that DELETE requests with a body are allowed, it seems that a number of
195
- # documentation sites discourage its use. Thus, it's possible that, depending on the server API
196
- # framework, the DELETE request could be rejected. As such, we're disallowing it here, BUT if we
197
- # get feedback from users that it should be supported, we can add support for it.
198
- raise 'DELETE requests without URI parameters are not allowed'
199
- # define_method(endpoint_name_as_sym) do |auth_token|
200
- # RestClientResources.execute_delete_authenticated self, endpoint, auth_token, {}
201
- # end
202
262
  end
203
263
  end
204
264
  else
205
- raise 'Unauthenticated DELETE requests are not allowed'
206
- # Bubbles::RestEnvironment.class_exec do
207
- # define_method(endpoint_name_as_sym) do
208
- # RestClientResources.execute_delete_unauthenticated self, endpoint
209
- # end
210
- # end
265
+ # XXX_jwir3: While MDN states that DELETE requests with a body are allowed, it seems that a number of
266
+ # documentation sites discourage its use. Thus, it's possible that, depending on the server API
267
+ # framework, the DELETE request could be rejected. In addition, RestClient doesn't seem to support DELETE
268
+ # requests with a body, so we're a bit stuck on this one, even if we wanted to support it.
269
+ raise 'DELETE requests without URI parameters are not allowed'
211
270
  end
212
271
  elsif endpoint.method == :patch
213
272
  if endpoint.authenticated?
214
273
  Bubbles::RestEnvironment.class_exec do
215
274
  if endpoint.has_uri_params?
216
275
  define_method(endpoint_name_as_sym) do |auth_token, uri_params, data|
217
- RestClientResources.execute_patch_authenticated self, endpoint, auth_token, uri_params, data
276
+ RestClientResources.execute_patch_authenticated self, endpoint, auth_token, uri_params, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
218
277
  end
219
278
  else
220
279
  define_method(endpoint_name_as_sym) do |auth_token, data|
221
- # TODO: Nothing tests this case. We need something to test this case or we run the risk of
222
- # it having bugs (uri_params was nil previously!)
223
- RestClientResources.execute_patch_authenticated self, endpoint, auth_token, {}, data
280
+ RestClientResources.execute_patch_authenticated self, endpoint, auth_token, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
224
281
  end
225
282
  end
226
283
  end
@@ -228,11 +285,11 @@ module Bubbles
228
285
  Bubbles::RestEnvironment.class_exec do
229
286
  if endpoint.has_uri_params?
230
287
  define_method(endpoint_name_as_sym) do |uri_params, data|
231
- RestClientResources.execute_patch_unauthenticated self, endpoint, uri_params, data
288
+ RestClientResources.execute_patch_unauthenticated self, endpoint, uri_params, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
232
289
  end
233
290
  else
234
291
  define_method(endpoint_name_as_sym) do |data|
235
- RestClientResources.execute_patch_unauthenticated self, endpoint, {}, data
292
+ RestClientResources.execute_patch_unauthenticated self, endpoint, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
236
293
  end
237
294
  end
238
295
  end
@@ -242,26 +299,23 @@ module Bubbles
242
299
  Bubbles::RestEnvironment.class_exec do
243
300
  if endpoint.has_uri_params?
244
301
  define_method(endpoint_name_as_sym) do |auth_token, uri_params, data|
245
- RestClientResources.execute_put_authenticated self, endpoint, auth_token, uri_params, data
302
+ RestClientResources.execute_put_authenticated self, endpoint, auth_token, uri_params, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
246
303
  end
247
304
  else
248
305
  define_method(endpoint_name_as_sym) do |auth_token, data|
249
- # TODO: Nothing tests this case. We need something to test this case or we run the risk of
250
- # it having bugs (uri_params was nil previously!)
251
- RestClientResources.execute_put_authenticated self, endpoint, auth_token, {}, data
306
+ RestClientResources.execute_put_authenticated self, endpoint, auth_token, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
252
307
  end
253
308
  end
254
309
  end
255
310
  else
256
- # raise 'Unauthenticated PUT requests are not implemented'
257
311
  Bubbles::RestEnvironment.class_exec do
258
312
  if endpoint.has_uri_params?
259
313
  define_method(endpoint_name_as_sym) do |uri_params, data|
260
- RestClientResources.execute_put_unauthenticated self, endpoint, uri_params, data
314
+ RestClientResources.execute_put_unauthenticated self, endpoint, uri_params, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
261
315
  end
262
316
  else
263
317
  define_method(endpoint_name_as_sym) do |data|
264
- RestClientResources.execute_put_unauthenticated self, endpoint, {}, data
318
+ RestClientResources.execute_put_unauthenticated self, endpoint, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
265
319
  end
266
320
  end
267
321
  end
@@ -271,23 +325,11 @@ module Bubbles
271
325
  Bubbles::RestEnvironment.class_exec do
272
326
  if endpoint.has_uri_params?
273
327
  define_method(endpoint_name_as_sym) do |auth_token, uri_params|
274
- RestClientResources.execute_head_authenticated self, endpoint, auth_token, uri_params
328
+ RestClientResources.execute_head_authenticated self, endpoint, auth_token, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
275
329
  end
276
330
  else
277
331
  define_method(endpoint_name_as_sym) do |auth_token|
278
- RestClientResources.execute_head_authenticated self, endpoint, auth_token, {}
279
- end
280
- end
281
- end
282
- elsif endpoint.api_key_required?
283
- Bubbles::RestEnvironment.class_exec do
284
- if endpoint.has_uri_params?
285
- define_method(endpoint_name_as_sym) do |uri_params|
286
- RestClientResources.execute_head_unauthenticated_with_uri_params self, endpoint, self.api_key, uri_params
287
- end
288
- else
289
- define_method(endpoint_name_as_sym) do
290
- RestClientResources.execute_head_unauthenticated self, endpoint, self.api_key, nil
332
+ RestClientResources.execute_head_authenticated self, endpoint, auth_token, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
291
333
  end
292
334
  end
293
335
  end
@@ -295,11 +337,11 @@ module Bubbles
295
337
  Bubbles::RestEnvironment.class_exec do
296
338
  if endpoint.has_uri_params?
297
339
  define_method(endpoint_name_as_sym) do |uri_params|
298
- RestClientResources.execute_head_unauthenticated self, endpoint, uri_params, {}
340
+ RestClientResources.execute_head_unauthenticated self, endpoint, uri_params, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
299
341
  end
300
342
  else
301
343
  define_method(endpoint_name_as_sym) do
302
- RestClientResources.execute_head_unauthenticated self, endpoint, {}, {}
344
+ RestClientResources.execute_head_unauthenticated self, endpoint, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
303
345
  end
304
346
  end
305
347
  end
@@ -74,13 +74,14 @@ module Bubbles
74
74
  # @param [Array<Symbol>] encode_authorization Parameters that should be treated as authorization parameters and
75
75
  # encoded using a Base64 encoding.
76
76
  #
77
- def initialize(method, location, auth_required = false, api_key_required = false, name = nil, return_type = :body_as_string, encode_authorization = {})
77
+ def initialize(method, location, auth_required = false, api_key_required = false, name = nil, return_type = :body_as_string, encode_authorization = {}, headers = {})
78
78
  @method = method
79
79
  @location = location
80
80
  @auth_required = auth_required
81
81
  @api_key_required = api_key_required
82
82
  @name = name
83
83
  @encode_authorization = encode_authorization
84
+ @additional_headers = headers
84
85
 
85
86
  unless Endpoint::RETURN_TYPES.include? return_type.to_s
86
87
  return_type = :body_as_string
@@ -145,13 +146,10 @@ module Bubbles
145
146
  #
146
147
  # @param [RestEnvironment] env The +RestEnvironment+ to use to access this +Endpoint+.
147
148
  #
148
- # @return [String] A +String+ containing the full URL to access this +Endpoint+ on the given {RestEnvironment}.
149
+ # @return [Addressable::URI] An +Addressable::URI+ containing the full URL to access this +Endpoint+ on the given
150
+ # +RestEnvironment+.
149
151
  #
150
152
  def get_expanded_url(env, uri_params = {})
151
- unless uri_params
152
- uri_params = {}
153
- end
154
-
155
153
  url = get_base_url env
156
154
 
157
155
  if is_complex?
@@ -239,7 +237,7 @@ module Bubbles
239
237
  # for the +Endpoint+, to be defined on {RestClientResources}; false, otherwise.
240
238
  #
241
239
  def name?
242
- @name == nil
240
+ @name != nil
243
241
  end
244
242
 
245
243
  ##
@@ -272,5 +270,17 @@ module Bubbles
272
270
  def has_uri_params?
273
271
  !@uri_params.empty?
274
272
  end
273
+
274
+ def additional_headers
275
+ unless @additional_headers
276
+ @additional_headers = {}
277
+ end
278
+
279
+ @additional_headers
280
+ end
281
+
282
+ def has_additional_headers?
283
+ not additional_headers.empty?
284
+ end
275
285
  end
276
286
  end