bubblez 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.
data/bubblez.gemspec ADDED
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bubblez/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = Bubblez::VersionInformation.package_name
8
+ spec.version = Bubblez::VersionInformation.version_name
9
+ spec.date = Date.today.strftime("%Y-%m-%d")
10
+ spec.summary = 'Bubblez REST Client'
11
+ spec.homepage = 'https://github.com/FoamFactory/bubblez'
12
+ spec.authors = ['Scott Johnson']
13
+ spec.email = 'jaywir3@gmail.com'
14
+ spec.files = %w(lib/bubblez.rb lib/bubblez/rest_environment.rb lib/bubblez/version.rb)
15
+ spec.license = 'MPL-2.0'
16
+ spec.summary = %q{A gem for easily defining client REST interfaces in Ruby}
17
+ spec.description = %q{Retrofit, by Square, allows you to easily define annoations that will generate the necessary boilerplate code for your REST interfaces. Bubblez is a Gem that seeks to bring a similar style of boilerplate generation to Ruby.}
18
+
19
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
20
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
21
+ if spec.respond_to?(:metadata)
22
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
23
+ else
24
+ raise "RubyGems 2.0 or newer is required to protect against " \
25
+ "public gem pushes."
26
+ end
27
+
28
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
29
+ f.match(%r{^(test|spec|features)/})
30
+ end
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+
35
+ spec.add_development_dependency "bundler", "~> 2.2.26"
36
+ spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
37
+ spec.add_development_dependency "minitest", "~> 5.0"
38
+ spec.add_development_dependency "minitest-reporters", "~> 1.1"
39
+ spec.add_development_dependency "simplecov", "~> 0.16"
40
+ spec.add_development_dependency "webmock", "~> 3.5"
41
+ spec.add_development_dependency "vcr", "~> 3.0"
42
+ spec.add_development_dependency "rspec", "~> 3.8"
43
+ spec.add_development_dependency "os", "~> 1.1.4"
44
+ spec.add_dependency "addressable", "~> 2.5"
45
+ spec.add_dependency "rest-client", "~> 2.0"
46
+ end
@@ -0,0 +1,353 @@
1
+ require 'bubblez/rest_environment'
2
+ require 'bubblez/endpoint'
3
+ require 'base64'
4
+
5
+ module Bubblez
6
+ class << self
7
+ attr_writer :configuration
8
+ end
9
+
10
+ ##
11
+ # Configure the Bubblez instance.
12
+ #
13
+ # Use this method if you want to configure the Bubblez instance, typically during initialization of your Gem or
14
+ # application.
15
+ #
16
+ # @example In app/config/initializers/bubblez.rb
17
+ # Bubblez.configure do |config|
18
+ # config.endpoints = [
19
+ # {
20
+ # :type => :get,
21
+ # :location => :version,
22
+ # :authenticated => false,
23
+ # :api_key_required => false
24
+ # }
25
+ # ]
26
+ # end
27
+ def self.configure
28
+ yield(configuration)
29
+ end
30
+
31
+ def self.configuration
32
+ @configuration ||= Configuration.new
33
+ end
34
+
35
+ ##
36
+ # The configuration of the Bubblez rest client.
37
+ #
38
+ # Use this class if you want to retrieve configuration values set during initialization.
39
+ #
40
+ class Configuration
41
+ def initialize
42
+ @environments = Hash.new
43
+ @endpoints = Hash.new
44
+ end
45
+
46
+ ##
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
+ #
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.
56
+ #
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])
78
+ end
79
+
80
+ ##
81
+ # Set the environments that can be used.
82
+ #
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.
87
+ #
88
+ # @example In app/config/environments/staging.rb:
89
+ # Bubblez.configure do |config|
90
+ # config.environments = [{
91
+ # :scheme => 'https',
92
+ # :host => 'stage.api.somehost.com',
93
+ # :port => '443',
94
+ # :api_key => 'something',
95
+ # :api_key_name => 'X-API-Key' # Optional
96
+ # }]
97
+ # end
98
+ #
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
121
+ end
122
+
123
+ ##
124
+ # Retrieve the list of +Endpoint+s configured in this +Configuration+ object.
125
+ #
126
+ # @return {Array} An Array of {Endpoint}s.
127
+ #
128
+ def endpoints
129
+ @endpoints
130
+ end
131
+
132
+ ##
133
+ # Add all {Endpoint} objects within this {Configuration} instance.
134
+ #
135
+ # {Endpoint} objects are defined using two required parameters: type and location, and three optional parameters:
136
+ # authenticated, api_key_required and name.
137
+ # - method: Indicates the HTTP method used to access the endpoint. Must be one of {Endpoint::METHODS}.
138
+ # - location: Indicates the path at which the {Endpoint} can be accessed on the host environment.
139
+ # - authenticated: (Optional) A true or false value indicating whether the {Endpoint} requires an authorization
140
+ # token to access it. Defaults to false.
141
+ # - api_key_required: (Optional) A true or false value indicating whether the {Endpoint} requires a API key to
142
+ # access it. Defaults to false.
143
+ # - name: (Optional): A +String+ indicating the name of the method to add. If not provided, the method name will
144
+ # be the same as the +location+.
145
+ #
146
+ def endpoints=(endpoints)
147
+ new_endpoints = Hash.new
148
+ endpoints.each do |ep|
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]
150
+
151
+ new_endpoints[endpoint_object.get_key_string] = endpoint_object
152
+ end
153
+
154
+ @endpoints = new_endpoints
155
+
156
+ # Define all of the endpoints as methods on RestEnvironment
157
+ @endpoints.values.each do |endpoint|
158
+ if endpoint.name != nil
159
+ endpoint_name_as_sym = endpoint.name.to_sym
160
+ else
161
+ endpoint_name_as_sym = endpoint.get_location_string.to_sym
162
+ end
163
+
164
+ if Bubblez::RestEnvironment.instance_methods(false).include?(endpoint_name_as_sym)
165
+ Bubblez::RestEnvironment.class_exec do
166
+ remove_method endpoint_name_as_sym
167
+ end
168
+ end
169
+
170
+ if endpoint.method == :get
171
+ if endpoint.authenticated?
172
+ Bubblez::RestEnvironment.class_exec do
173
+ if endpoint.has_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
187
+ end
188
+ else
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
203
+ end
204
+ end
205
+ end
206
+ else
207
+ Bubblez::RestEnvironment.class_exec do
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
216
+ end
217
+ end
218
+ end
219
+ elsif endpoint.method == :post
220
+ if endpoint.authenticated? and !endpoint.encode_authorization_header?
221
+ Bubblez::RestEnvironment.class_exec do
222
+ define_method(endpoint_name_as_sym) do |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
224
+ end
225
+ end
226
+ elsif endpoint.encode_authorization_header?
227
+ Bubblez::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
+ }
233
+
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
+ Bubblez::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
246
+ end
247
+ end
248
+ end
249
+ elsif endpoint.method == :delete
250
+ if endpoint.has_uri_params?
251
+ if endpoint.authenticated?
252
+ Bubblez::RestEnvironment.class_exec do
253
+ define_method(endpoint_name_as_sym) do |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
+ Bubblez::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
261
+ end
262
+ end
263
+ end
264
+ else
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'
270
+ end
271
+ elsif endpoint.method == :patch
272
+ if endpoint.authenticated?
273
+ Bubblez::RestEnvironment.class_exec do
274
+ if endpoint.has_uri_params?
275
+ define_method(endpoint_name_as_sym) do |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
277
+ end
278
+ else
279
+ define_method(endpoint_name_as_sym) do |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
281
+ end
282
+ end
283
+ end
284
+ else
285
+ Bubblez::RestEnvironment.class_exec do
286
+ if endpoint.has_uri_params?
287
+ define_method(endpoint_name_as_sym) do |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
289
+ end
290
+ else
291
+ define_method(endpoint_name_as_sym) do |data|
292
+ RestClientResources.execute_patch_unauthenticated self, endpoint, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
293
+ end
294
+ end
295
+ end
296
+ end
297
+ elsif endpoint.method == :put
298
+ if endpoint.authenticated?
299
+ Bubblez::RestEnvironment.class_exec do
300
+ if endpoint.has_uri_params?
301
+ define_method(endpoint_name_as_sym) do |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
303
+ end
304
+ else
305
+ define_method(endpoint_name_as_sym) do |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
307
+ end
308
+ end
309
+ end
310
+ else
311
+ Bubblez::RestEnvironment.class_exec do
312
+ if endpoint.has_uri_params?
313
+ define_method(endpoint_name_as_sym) do |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
315
+ end
316
+ else
317
+ define_method(endpoint_name_as_sym) do |data|
318
+ RestClientResources.execute_put_unauthenticated self, endpoint, {}, data, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
319
+ end
320
+ end
321
+ end
322
+ end
323
+ elsif endpoint.method == :head
324
+ if endpoint.authenticated?
325
+ Bubblez::RestEnvironment.class_exec do
326
+ if endpoint.has_uri_params?
327
+ define_method(endpoint_name_as_sym) do |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
329
+ end
330
+ else
331
+ define_method(endpoint_name_as_sym) do |auth_token|
332
+ RestClientResources.execute_head_authenticated self, endpoint, auth_token, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
333
+ end
334
+ end
335
+ end
336
+ else
337
+ Bubblez::RestEnvironment.class_exec do
338
+ if endpoint.has_uri_params?
339
+ define_method(endpoint_name_as_sym) do |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
341
+ end
342
+ else
343
+ define_method(endpoint_name_as_sym) do
344
+ RestClientResources.execute_head_unauthenticated self, endpoint, {}, endpoint.additional_headers, self.get_api_key_if_needed(endpoint), self.api_key_name
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+ end
351
+ end
352
+ end
353
+ end
@@ -0,0 +1,286 @@
1
+ require 'addressable/template'
2
+
3
+ module Bubblez
4
+ ##
5
+ # Representation of a single API endpoint within the Bubblez infrastructure.
6
+ #
7
+ # In order to access an API Endpoint, an {RestEnvironment} must also be provided. This class is an abstract
8
+ # representation of an +Endpoint+, without any information provided as part of the Environment. In other words, an
9
+ # Endpoint can be used with any +RestEnvironment+.
10
+ #
11
+ class Endpoint
12
+ ##
13
+ # Controls the method used to access the endpoint. Must be one of {Endpoint::Methods}.
14
+ # @return [Symbol] the method used to access the endpoint. Will always be one of the symbols defined in
15
+ # {Endpoint::METHODS}.
16
+ attr_accessor :method
17
+
18
+ ##
19
+ # Controls the location, relative to the web root of the host, used to access the endpoint.
20
+ # @return [String] the location relative to the web root of the host used to access the endpoint
21
+ attr_accessor :location
22
+
23
+ ##
24
+ # Controls whether authentication is required to access this endpoint. Defaults to false.
25
+ # @return [Boolean] true, if authentication is required to access this endpoint; false, otherwise.
26
+ attr_accessor :authentication_required
27
+
28
+ ##
29
+ # Controls whether an API key is required to access this endpoint. Defaults to false.
30
+ # @return [Boolean] true, if an API key is required to access this endpoint; false, otherwise.
31
+ attr_accessor :api_key_required
32
+
33
+ ##
34
+ # Controls what type of object will be returned from the REST API call on success. Must be one of the symbols
35
+ # defined in {Endpoint::RETURN_TYPES}.
36
+ #
37
+ attr_accessor :return_type
38
+
39
+ ##
40
+ # Controls which data values should be encoded as part of an Authorization header. They will be separated with a
41
+ # colon in the order they are received and Base64-encoded.
42
+ # @return [Array] An array of +Symbol+s specifying which of the data attributes should be Base64-encoded as part of
43
+ # an Authorization header. The values will be encoded in the order they are received.
44
+ attr_accessor :encode_authorization
45
+
46
+ ##
47
+ # An array of parameters that are specified on the URI of this endpoint for each call.
48
+ attr_accessor :uri_params
49
+
50
+ ## A template for specifying the complete URL for endpoints.
51
+ API_URL = ::Addressable::Template.new("{scheme}://{host}/{endpoint}")
52
+
53
+ ## A template for specifying the complete URL for endpoints, with a port attached to the host.
54
+ API_URL_WITH_PORT = ::Addressable::Template.new("{scheme}://{host}:{port}/{endpoint}")
55
+
56
+ ## The HTTP methods supported by a rest client utilizing Bubblez.
57
+ METHODS = %w[get post patch put delete head].freeze
58
+
59
+ ## The possible return types for successful REST calls. Defaults to :body_as_string.
60
+ RETURN_TYPES = %w[full_response body_as_string body_as_object].freeze
61
+
62
+ ##
63
+ # Construct a new instance of an Endpoint.
64
+ #
65
+ # @param [Symbol] method The type of the new Endpoint to create. Must be one of the methods in
66
+ # {Endpoint::METHODS}.
67
+ # @param [String] location The location, relative to the root of the host, at which the endpoint resides.
68
+ # @param [Boolean] auth_required If true, then authorization/authentication is required to access this endpoint.
69
+ # Defaults to +false+.
70
+ # @param [Boolean] api_key_required If true, then an API key is required to access this endpoint. Defaults to
71
+ # +false+.
72
+ # @param [String] name An optional name which will be given to the method that will execute this {Endpoint} within
73
+ # the context of a {RestClientResources} object.
74
+ # @param [Array<Symbol>] encode_authorization Parameters that should be treated as authorization parameters and
75
+ # encoded using a Base64 encoding.
76
+ #
77
+ def initialize(method, location, auth_required = false, api_key_required = false, name = nil, return_type = :body_as_string, encode_authorization = {}, headers = {})
78
+ @method = method
79
+ @location = location
80
+ @auth_required = auth_required
81
+ @api_key_required = api_key_required
82
+ @name = name
83
+ @encode_authorization = encode_authorization
84
+ @additional_headers = headers
85
+
86
+ unless Endpoint::RETURN_TYPES.include? return_type.to_s
87
+ return_type = :body_as_string
88
+ end
89
+
90
+ @return_type = return_type
91
+
92
+ @uri_params = []
93
+
94
+ # Strip the leading slash from the endpoint location, if it's there
95
+ if @location.to_s[0] == '/'
96
+ @location = @location.to_s.slice(1, @location.to_s.length)
97
+ end
98
+
99
+ # Extract URI parameters and create symbols for them
100
+ # URI parameters are enclosed by curly braces '{' and '}'
101
+ @location.to_s.split('/').each do |uri_segment|
102
+
103
+ match_data = /\{(.*)\}/.match(uri_segment)
104
+ unless match_data == nil
105
+ @uri_params.push(match_data[1].to_sym)
106
+ end
107
+ end
108
+ end
109
+
110
+ ##
111
+ # Retrieve a +String+ that will identify this +Endpoint+ uniquely within a hash table.
112
+ #
113
+ # @return [String] A unique identifier for this Endpoint, including its method (get/post/put/etc..), location, whether or not it is authenticated, and whether it needs an API key to successfully execute.
114
+ #
115
+ def get_key_string
116
+ auth_string = '-unauthenticated'
117
+ if @auth_required
118
+ auth_string = '-authenticated'
119
+ end
120
+
121
+ api_key_string = ''
122
+ if @api_key_required
123
+ api_key_string = '-with-api-key'
124
+ end
125
+
126
+ method.to_s + "-" + @location.to_s + auth_string + api_key_string
127
+ end
128
+
129
+ ##
130
+ # Retrieve the base URL template for this +Endpoint+, given a +RestEnvironment+.
131
+ #
132
+ # @param [RestEnvironment] env The +RestEnvironment+ to use to access this endpoint.
133
+ #
134
+ # @return [Addressable::Template] A +Template+ containing the URL to use to access this +Endpoint+.
135
+ #
136
+ def get_base_url(env)
137
+ unless env.port == 80 || env.port == 443
138
+ return API_URL_WITH_PORT
139
+ end
140
+
141
+ API_URL
142
+ end
143
+
144
+ ##
145
+ # Retrieve the URL to access this +Endpoint+, as a +String+ with all parameters expanded.
146
+ #
147
+ # @param [RestEnvironment] env The +RestEnvironment+ to use to access this +Endpoint+.
148
+ #
149
+ # @return [Addressable::URI] An +Addressable::URI+ containing the full URL to access this +Endpoint+ on the given
150
+ # +RestEnvironment+.
151
+ #
152
+ def get_expanded_url(env, uri_params = {})
153
+ url = get_base_url env
154
+
155
+ if is_complex?
156
+ special_url_string = '{scheme}://{host}/'
157
+ unless @port == 80 || @port == 443
158
+ special_url_string = '{scheme}://{host}:{port}/'
159
+ end
160
+
161
+ special_url_string = special_url_string + @location
162
+
163
+ uri_params.each do |param, value|
164
+ needle = "{#{param.to_s}}"
165
+ special_url_string = special_url_string.sub(needle, value.to_s)
166
+ end
167
+
168
+ url = ::Addressable::Template.new(special_url_string)
169
+
170
+ return url.expand(scheme: env.scheme, host: env.host, port: env.port)
171
+ end
172
+
173
+ url.expand(scheme: env.scheme, host: env.host, port: env.port, endpoint: @location)
174
+ end
175
+
176
+ ##
177
+ # Determine if the location for this Endpoint is complex.
178
+ #
179
+ # @return [Boolean] true, if the location for this Endpoint is complex (contains a '/'); false, otherwise.
180
+ def is_complex?
181
+ @location.include? '/'
182
+ end
183
+
184
+ ##
185
+ # Retrieve a String representing the location of this Endpoint.
186
+ #
187
+ # Complex Endpoints will have instances of '/' replaced with '_'.
188
+ #
189
+ # @return [String] The string representation of the location of this endpoint.
190
+ def get_location_string
191
+ unless is_complex?
192
+ return @location
193
+ end
194
+
195
+ @location.to_s.gsub('/', '_')
196
+ end
197
+
198
+ ##
199
+ # Determine if this +Endpoint+ requires authentication/authorization to utilize
200
+ #
201
+ # @return [Boolean] true, if this +Endpoint+ requires authentication/authorization to use; false, otherwise.
202
+ def authenticated?
203
+ @auth_required
204
+ end
205
+
206
+ ##
207
+ # Determine if an API key is required
208
+ #
209
+ # @return [Boolean] true, if an API key is required to make the request; false, otherwise.
210
+ def api_key_required?
211
+ api_key_required
212
+ end
213
+
214
+ ##
215
+ # Set the name of the method on {RestClientResources} used to access this {Endpoint}.
216
+ #
217
+ # @param [String] name The name of the method used to access this {Endpoint}.
218
+ #
219
+ def name=(name)
220
+ @name = name
221
+ end
222
+
223
+ ##
224
+ # Retrieve the name of the method on {RestClientResources} used to access this {Endpoint}.
225
+ #
226
+ # @return [String] A String containing the name of the method on {RestClientResources} used to access this
227
+ # {Endpoint}, or +nil+ if one wasn't provided.
228
+ #
229
+ def name
230
+ @name
231
+ end
232
+
233
+ ##
234
+ # Determine if this {Endpoint} has a method name, different from the +location+ name, specified for it.
235
+ #
236
+ # @return [Boolean] true, if this {Endpoint} has a method name that is different than the +location+ name specified
237
+ # for the +Endpoint+, to be defined on {RestClientResources}; false, otherwise.
238
+ #
239
+ def name?
240
+ @name != nil
241
+ end
242
+
243
+ ##
244
+ # Whether or not an Authorization header should be Base64-encoded.
245
+ #
246
+ # @return [Boolean] true, if attributes from the data array have been specified to be Base64-encoded as part of an
247
+ # Authorization header; false, otherwise.
248
+ #
249
+ def encode_authorization_header?
250
+ !@encode_authorization.nil? and @encode_authorization.length > 0
251
+ end
252
+
253
+ ##
254
+ # Retrieve the return type of this REST endpoint.
255
+ #
256
+ # This will always be one of:
257
+ #
258
+ # - +full_response+ : Indicates that the full +Response+ object should be returned so that headers and
259
+ # return code can be used.
260
+ # - +body_as_object+ : Indicates that the body of the +Response+ should be parsed as a full +OpenStruct+
261
+ # object and returned.
262
+ # - +body_as_string+ : Indicates that only the body of the +Response+ object should be returned, as a +String+.
263
+ #
264
+ # By default, if this is not specified, it will be +body_as+string+.
265
+ #
266
+ def return_type
267
+ @return_type
268
+ end
269
+
270
+ def has_uri_params?
271
+ !@uri_params.empty?
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
285
+ end
286
+ end