crapi 0.1.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/crapi/client.rb CHANGED
@@ -5,60 +5,60 @@ require 'openssl'
5
5
  require 'crapi/proxy'
6
6
  require 'crapi/errors'
7
7
 
8
- module Crapi
9
- ## Provides a connection mechanism, simple CRUD methods ({#delete} / {#get} / {#patch} / {#post} /
10
- ## {#put}), and proxy generators.
11
- ##
8
+ module CrAPI
9
+ # Provides a connection mechanism, simple CRUD methods ({#delete} / {#get} / {#patch} / {#post} /
10
+ # {#put}), and proxy generators.
11
+ #
12
12
  class Client
13
- ## A Hash containing headers to send with every request (unless overriden elsewhere). Headers
14
- ## set by the user via the CRUD methods' *headers* still override any conflicting default
15
- ## header.
16
- ##
13
+ # A Hash containing headers to send with every request (unless overriden elsewhere). Headers
14
+ # set by the user via the CRUD methods' *headers* still override any conflicting default
15
+ # header.
16
+ #
17
17
  attr_accessor :default_headers
18
18
 
19
- ## The content-type for JSON data.
20
- ##
19
+ # The content-type for JSON data.
20
+ #
21
21
  JSON_CONTENT_TYPE = 'application/json'.freeze
22
22
 
23
- ## The content-type for FORM data.
24
- ##
23
+ # The content-type for FORM data.
24
+ #
25
25
  FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded'.freeze
26
26
 
27
- ## @param base_uri [URI, String]
28
- ## The base URI the client should use for determining the host to connect to, determining
29
- ## whether SSH is applicable, and setting the base path for subsequent CRUD calls.
30
- ##
31
- ## @param opts [Hash]
32
- ## Method options. All method options are **optional** in this particular case.
33
- ##
34
- ## @option opts [true, false] :insecure
35
- ## Whether to allow insecure SSH connections (i.e. don't attempt to verify the validity of the
36
- ## given certificate).
37
- ##
38
- ## @option opts [String] :proxy_host
39
- ## The DNS name or IP address of a proxy server to use when connecting to the target system.
40
- ## Maps to `Net::HTTP#new`'s *p_addr*.
41
- ##
42
- ## @option opts [Number] :proxy_port
43
- ## The proxy server port to use when connecting to the target system.
44
- ## Maps to `Net::HTTP#new`'s *p_port*.
45
- ##
46
- ## @option opts [String] :proxy_username
47
- ## The username to give if authorization is required to access the specified proxy host.
48
- ## Maps to `Net::HTTP#new`'s *p_user*.
49
- ##
50
- ## @option opts [Number] :proxy_password
51
- ## The password to give if authorization is required to access the specified proxy host.
52
- ## Maps to `Net::HTTP#new`'s *p_pass*.
53
- ##
54
- ##
55
- ## @raise [Crapi::ArgumentError]
56
- ##
27
+ # @param base_uri [URI, String]
28
+ # The base URI the client should use for determining the host to connect to, determining
29
+ # whether SSH is applicable, and setting the base path for subsequent CRUD calls.
30
+ #
31
+ # @param opts [Hash]
32
+ # Method options. All method options are **optional** in this particular case.
33
+ #
34
+ # @option opts [true, false] :insecure
35
+ # Whether to allow insecure SSH connections (i.e. don't attempt to verify the validity of the
36
+ # given certificate).
37
+ #
38
+ # @option opts [String] :proxy_host
39
+ # The DNS name or IP address of a proxy server to use when connecting to the target system.
40
+ # Maps to `Net::HTTP#new`'s *p_addr*.
41
+ #
42
+ # @option opts [Number] :proxy_port
43
+ # The proxy server port to use when connecting to the target system.
44
+ # Maps to `Net::HTTP#new`'s *p_port*.
45
+ #
46
+ # @option opts [String] :proxy_username
47
+ # The username to give if authorization is required to access the specified proxy host.
48
+ # Maps to `Net::HTTP#new`'s *p_user*.
49
+ #
50
+ # @option opts [Number] :proxy_password
51
+ # The password to give if authorization is required to access the specified proxy host.
52
+ # Maps to `Net::HTTP#new`'s *p_pass*.
53
+ #
54
+ #
55
+ # @raise [CrAPI::ArgumentError]
56
+ #
57
57
  def initialize(base_uri, opts = {})
58
58
  @base_uri = case base_uri
59
59
  when URI then base_uri
60
60
  when String then URI(base_uri)
61
- else raise Crapi::ArgumentError, %(Unexpected "base_uri" type: #{base_uri.class})
61
+ else raise CrAPI::ArgumentError, %(Unexpected "base_uri" type: #{base_uri.class})
62
62
  end
63
63
 
64
64
  @proxy_host = opts[:proxy_host]
@@ -74,41 +74,41 @@ module Crapi
74
74
  @default_headers = { 'Content-Type': JSON_CONTENT_TYPE }.with_indifferent_access
75
75
  end
76
76
 
77
- ## Returns a new {Crapi::Proxy Crapi::Proxy} for this client.
78
- ##
79
- ##
80
- ## @param segment [String]
81
- ## The segment to add to this client's path.
82
- ##
83
- ## @param headers [Hash]
84
- ## The default headers for the new proxy.
85
- ##
86
- ##
87
- ## @return [Crapi::Proxy]
88
- ##
77
+ # Returns a new {CrAPI::Proxy CrAPI::Proxy} for this client.
78
+ #
79
+ #
80
+ # @param segment [String]
81
+ # The segment to add to this client's path.
82
+ #
83
+ # @param headers [Hash]
84
+ # The default headers for the new proxy.
85
+ #
86
+ #
87
+ # @return [CrAPI::Proxy]
88
+ #
89
89
  def new_proxy(segment = '/', headers: nil)
90
90
  Proxy.new(add: segment, to: self, headers: headers)
91
91
  end
92
92
 
93
- ## CRUD methods ...
94
-
95
- ## CRUD method: DELETE
96
- ##
97
- ## @param path [String]
98
- ## The path to the resource to DELETE. Note that this path is always interpreted as relative
99
- ## to the client's base_uri's path, regardless of whether it begins with a "/".
100
- ##
101
- ## @param headers [Hash]
102
- ## Additional headers to set in addition to the client's defaults. Any header given here and
103
- ## also appearing in the client's defaults will override said default value.
104
- ##
105
- ## @param query [Hash, Array, String]
106
- ## Query string values, if any, to append to the given path. Strings are appended as-is;
107
- ## Hashes and Arrays are serialized as URI-encoded form data before appending.
108
- ##
109
- ##
110
- ## @return [Object]
111
- ##
93
+ # CRUD methods ...
94
+
95
+ # CRUD method: DELETE
96
+ #
97
+ # @param path [String]
98
+ # The path to the resource to DELETE. Note that this path is always interpreted as relative
99
+ # to the client's base_uri's path, regardless of whether it begins with a "/".
100
+ #
101
+ # @param headers [Hash]
102
+ # Additional headers to set in addition to the client's defaults. Any header given here and
103
+ # also appearing in the client's defaults will override said default value.
104
+ #
105
+ # @param query [Hash, Array, String]
106
+ # Query string values, if any, to append to the given path. Strings are appended as-is;
107
+ # Hashes and Arrays are serialized as URI-encoded form data before appending.
108
+ #
109
+ #
110
+ # @return [Object]
111
+ #
112
112
  def delete(path, headers: {}, query: {})
113
113
  headers = @default_headers.merge(headers)
114
114
 
@@ -117,23 +117,23 @@ module Crapi
117
117
  parse_response(response)
118
118
  end
119
119
 
120
- ## CRUD method: GET
121
- ##
122
- ## @param path [String]
123
- ## The path to the resource to GET. Note that this path is always interpreted as relative to
124
- ## the client's base_uri's path, regardless of whether it begins with a "/".
125
- ##
126
- ## @param headers [Hash]
127
- ## Additional headers to set in addition to the client's defaults. Any header given here and
128
- ## also appearing in the client's defaults will override said default value.
129
- ##
130
- ## @param query [Hash, Array, String]
131
- ## Query string values, if any, to append to the given path. Strings are appended as-is;
132
- ## Hashes and Arrays are serialized as URI-encoded form data before appending.
133
- ##
134
- ##
135
- ## @return [Object]
136
- ##
120
+ # CRUD method: GET
121
+ #
122
+ # @param path [String]
123
+ # The path to the resource to GET. Note that this path is always interpreted as relative to
124
+ # the client's base_uri's path, regardless of whether it begins with a "/".
125
+ #
126
+ # @param headers [Hash]
127
+ # Additional headers to set in addition to the client's defaults. Any header given here and
128
+ # also appearing in the client's defaults will override said default value.
129
+ #
130
+ # @param query [Hash, Array, String]
131
+ # Query string values, if any, to append to the given path. Strings are appended as-is;
132
+ # Hashes and Arrays are serialized as URI-encoded form data before appending.
133
+ #
134
+ #
135
+ # @return [Object]
136
+ #
137
137
  def get(path, headers: {}, query: {})
138
138
  headers = @default_headers.merge(headers)
139
139
 
@@ -142,27 +142,27 @@ module Crapi
142
142
  parse_response(response)
143
143
  end
144
144
 
145
- ## CRUD method: PATCH
146
- ##
147
- ## @param path [String]
148
- ## The path to the resource to PATCH. Note that this path is always interpreted as relative to
149
- ## the client's base_uri's path, regardless of whether it begins with a "/".
150
- ##
151
- ## @param headers [Hash]
152
- ## Additional headers to set in addition to the client's defaults. Any header given here and
153
- ## also appearing in the client's defaults will override said default value.
154
- ##
155
- ## @param query [Hash, Array, String]
156
- ## Query string values, if any, to append to the given path. Strings are appended as-is;
157
- ## Hashes and Arrays are serialized as URI-encoded form data before appending.
158
- ##
159
- ## @param payload [Hash, String]
160
- ## The payload to send, if any. Strings are used as-is; Hashes are serialized per the
161
- ## request's "Content-Type" header.
162
- ##
163
- ##
164
- ## @return [Object]
165
- ##
145
+ # CRUD method: PATCH
146
+ #
147
+ # @param path [String]
148
+ # The path to the resource to PATCH. Note that this path is always interpreted as relative to
149
+ # the client's base_uri's path, regardless of whether it begins with a "/".
150
+ #
151
+ # @param headers [Hash]
152
+ # Additional headers to set in addition to the client's defaults. Any header given here and
153
+ # also appearing in the client's defaults will override said default value.
154
+ #
155
+ # @param query [Hash, Array, String]
156
+ # Query string values, if any, to append to the given path. Strings are appended as-is;
157
+ # Hashes and Arrays are serialized as URI-encoded form data before appending.
158
+ #
159
+ # @param payload [Hash, String]
160
+ # The payload to send, if any. Strings are used as-is; Hashes are serialized per the
161
+ # request's "Content-Type" header.
162
+ #
163
+ #
164
+ # @return [Object]
165
+ #
166
166
  def patch(path, headers: {}, query: {}, payload: {})
167
167
  headers = @default_headers.merge(headers)
168
168
  payload = format_payload(payload, as: headers[:'Content-Type'])
@@ -172,27 +172,27 @@ module Crapi
172
172
  parse_response(response)
173
173
  end
174
174
 
175
- ## CRUD method: POST
176
- ##
177
- ## @param path [String]
178
- ## The path to the resource to POST. Note that this path is always interpreted as relative to
179
- ## the client's base_uri's path, regardless of whether it begins with a "/".
180
- ##
181
- ## @param headers [Hash]
182
- ## Additional headers to set in addition to the client's defaults. Any header given here and
183
- ## also appearing in the client's defaults will override said default value.
184
- ##
185
- ## @param query [Hash, Array, String]
186
- ## Query string values, if any, to append to the given path. Strings are appended as-is;
187
- ## Hashes and Arrays are serialized as URI-encoded form data before appending.
188
- ##
189
- ## @param payload [Hash, String]
190
- ## The payload to send, if any. Strings are used as-is; Hashes are serialized per the
191
- ## request's "Content-Type" header.
192
- ##
193
- ##
194
- ## @return [Object]
195
- ##
175
+ # CRUD method: POST
176
+ #
177
+ # @param path [String]
178
+ # The path to the resource to POST. Note that this path is always interpreted as relative to
179
+ # the client's base_uri's path, regardless of whether it begins with a "/".
180
+ #
181
+ # @param headers [Hash]
182
+ # Additional headers to set in addition to the client's defaults. Any header given here and
183
+ # also appearing in the client's defaults will override said default value.
184
+ #
185
+ # @param query [Hash, Array, String]
186
+ # Query string values, if any, to append to the given path. Strings are appended as-is;
187
+ # Hashes and Arrays are serialized as URI-encoded form data before appending.
188
+ #
189
+ # @param payload [Hash, String]
190
+ # The payload to send, if any. Strings are used as-is; Hashes are serialized per the
191
+ # request's "Content-Type" header.
192
+ #
193
+ #
194
+ # @return [Object]
195
+ #
196
196
  def post(path, headers: {}, query: {}, payload: {})
197
197
  headers = @default_headers.merge(headers)
198
198
  payload = format_payload(payload, as: headers[:'Content-Type'])
@@ -202,27 +202,27 @@ module Crapi
202
202
  parse_response(response)
203
203
  end
204
204
 
205
- ## CRUD method: PUT
206
- ##
207
- ## @param path [String]
208
- ## The path to the resource to PATCH. Note that this path is always interpreted as relative to
209
- ## the client's base_uri's path, regardless of whether it begins with a "/".
210
- ##
211
- ## @param headers [Hash]
212
- ## Additional headers to set in addition to the client's defaults. Any header given here and
213
- ## also appearing in the client's defaults will override said default value.
214
- ##
215
- ## @param query [Hash, Array, String]
216
- ## Query string values, if any, to append to the given path. Strings are appended as-is;
217
- ## Hashes and Arrays are serialized as URI-encoded form data before appending.
218
- ##
219
- ## @param payload [Hash, String]
220
- ## The payload to send, if any. Strings are used as-is; Hashes are serialized per the
221
- ## request's "Content-Type" header.
222
- ##
223
- ##
224
- ## @return [Object]
225
- ##
205
+ # CRUD method: PUT
206
+ #
207
+ # @param path [String]
208
+ # The path to the resource to PATCH. Note that this path is always interpreted as relative to
209
+ # the client's base_uri's path, regardless of whether it begins with a "/".
210
+ #
211
+ # @param headers [Hash]
212
+ # Additional headers to set in addition to the client's defaults. Any header given here and
213
+ # also appearing in the client's defaults will override said default value.
214
+ #
215
+ # @param query [Hash, Array, String]
216
+ # Query string values, if any, to append to the given path. Strings are appended as-is;
217
+ # Hashes and Arrays are serialized as URI-encoded form data before appending.
218
+ #
219
+ # @param payload [Hash, String]
220
+ # The payload to send, if any. Strings are used as-is; Hashes are serialized per the
221
+ # request's "Content-Type" header.
222
+ #
223
+ #
224
+ # @return [Object]
225
+ #
226
226
  def put(path, headers: {}, query: {}, payload: {})
227
227
  headers = @default_headers.merge(headers)
228
228
  payload = format_payload(payload, as: headers[:'Content-Type'])
@@ -232,27 +232,23 @@ module Crapi
232
232
  parse_response(response)
233
233
  end
234
234
 
235
- ##
236
-
237
235
  private
238
236
 
239
- ##
240
-
241
- ## Assembles a path and a query string Hash/Array/String into a URI path.
242
- ##
243
- ##
244
- ## @param path [String]
245
- ## The path to the desired resource.
246
- ##
247
- ## @param query [Hash, Array, String]
248
- ## Query string values, if any, to append to the given path. Strings are appended as-is;
249
- ## Hashes and Arrays are serialized as URI-encoded form data before appending.
250
- ##
251
- ##
252
- ## @raise [Crapi::ArgumentError]
253
- ##
254
- ## @return [String]
255
- ##
237
+ # Assembles a path and a query string Hash/Array/String into a URI path.
238
+ #
239
+ #
240
+ # @param path [String]
241
+ # The path to the desired resource.
242
+ #
243
+ # @param query [Hash, Array, String]
244
+ # Query string values, if any, to append to the given path. Strings are appended as-is;
245
+ # Hashes and Arrays are serialized as URI-encoded form data before appending.
246
+ #
247
+ #
248
+ # @raise [CrAPI::ArgumentError]
249
+ #
250
+ # @return [String]
251
+ #
256
252
  def full_path(path, query: {})
257
253
  path = [@base_uri.path, path].map { |i| i.gsub(%r{^/|/$}, '') }.keep_if(&:present?)
258
254
  path = "/#{path.join('/')}"
@@ -261,51 +257,51 @@ module Crapi
261
257
  path += case query
262
258
  when Hash, Array then "?#{URI.encode_www_form(query)}"
263
259
  when String then "?#{query}"
264
- else raise Crapi::ArgumentError, %(Unexpected "query" type: #{query.class})
260
+ else raise CrAPI::ArgumentError, %(Unexpected "query" type: #{query.class})
265
261
  end
266
262
  end
267
263
 
268
264
  path
269
265
  end
270
266
 
271
- ## Verifies the given value is that of a successful HTTP response.
272
- ##
273
- ##
274
- ## @param response [Net::HTTPResponse]
275
- ## The response to evaluate as "successful" or not.
276
- ##
277
- ##
278
- ## @raise [Crapi::BadHttpResponseError]
279
- ##
280
- ## @return [nil]
281
- ##
267
+ # Verifies the given value is that of a successful HTTP response.
268
+ #
269
+ #
270
+ # @param response [Net::HTTPResponse]
271
+ # The response to evaluate as "successful" or not.
272
+ #
273
+ #
274
+ # @raise [CrAPI::BadHttpResponseError]
275
+ #
276
+ # @return [nil]
277
+ #
282
278
  def ensure_success!(response)
283
279
  return if response.is_a? Net::HTTPSuccess
284
280
 
285
281
  message = "#{response.code} - #{response.message}"
286
282
  message += "\n#{response.body}" if response.body.present?
287
283
 
288
- raise Crapi::BadHttpResponseError, message
284
+ raise CrAPI::BadHttpResponseError, message
289
285
  end
290
286
 
291
- ## Serializes the given payload per the requested content-type.
292
- ##
293
- ##
294
- ## @param payload [Hash, String]
295
- ## The payload to format. Strings are returned as-is; Hashes are serialized per the given *as*
296
- ## content-type.
297
- ##
298
- ## @param as [String]
299
- ## The target content-type.
300
- ##
301
- ##
302
- ## @return [String]
303
- ##
287
+ # Serializes the given payload per the requested content-type.
288
+ #
289
+ #
290
+ # @param payload [Hash, String]
291
+ # The payload to format. Strings are returned as-is; Hashes are serialized per the given *as*
292
+ # content-type.
293
+ #
294
+ # @param as [String]
295
+ # The target content-type.
296
+ #
297
+ #
298
+ # @return [String]
299
+ #
304
300
  def format_payload(payload, as: JSON_CONTENT_TYPE)
305
- ## Non-Hash payloads are passed through as-is.
301
+ # Non-Hash payloads are passed through as-is.
306
302
  return payload unless payload.is_a? Hash
307
303
 
308
- ## Massage Hash-like payloads into a suitable format.
304
+ # Massage Hash-like payloads into a suitable format.
309
305
  case as
310
306
  when JSON_CONTENT_TYPE
311
307
  JSON.generate(payload.as_json)
@@ -316,15 +312,15 @@ module Crapi
316
312
  end
317
313
  end
318
314
 
319
- ## Parses the given response as its claimed content-type.
320
- ##
321
- ##
322
- ## @param response [Net::HTTPResponse]
323
- ## The response whose body is to be parsed.
324
- ##
325
- ##
326
- ## @return [Object]
327
- ##
315
+ # Parses the given response as its claimed content-type.
316
+ #
317
+ #
318
+ # @param response [Net::HTTPResponse]
319
+ # The response whose body is to be parsed.
320
+ #
321
+ #
322
+ # @return [Object]
323
+ #
328
324
  def parse_response(response)
329
325
  case response.content_type
330
326
  when JSON_CONTENT_TYPE
@@ -335,25 +331,25 @@ module Crapi
335
331
  end
336
332
  end
337
333
 
338
- ## Net::HTTP needs a shortcut instance method for PUT calls like it does for GET/DELETE/PATCH/POST.
339
- ##
334
+ # Net::HTTP needs a shortcut instance method for PUT calls like it does for GET/DELETE/PATCH/POST.
335
+ #
340
336
  class Net::HTTP
341
- ## Convenience PUT method monkey-patched into Net::HTTP.
342
- ##
343
- ## Net::HTTP provides handy methods for DELETE, GET, HEAD, OPTIONS, PATCH, and POST, **but not
344
- ## PUT**, so we have to monkey-patch one in. The parameters listed below were chosen to match
345
- ## those in use for the other Net::HTTP request methods in both name and meaning.
346
- ##
347
- ##
348
- ## @param path [String]
349
- ## @param data [String]
350
- ## @param initheader [Hash]
351
- ## @param dest [nil]
352
- ##
353
- ##
354
- ## @return [Net::HTTPResponse]
355
- ##
356
- ## @see https://docs.ruby-lang.org/en/trunk/Net/HTTP.html
337
+ # Convenience PUT method monkey-patched into Net::HTTP.
338
+ #
339
+ # Net::HTTP provides handy methods for DELETE, GET, HEAD, OPTIONS, PATCH, and POST, **but not
340
+ # PUT**, so we have to monkey-patch one in. The parameters listed below were chosen to match
341
+ # those in use for the other Net::HTTP request methods in both name and meaning.
342
+ #
343
+ #
344
+ # @param path [String]
345
+ # @param data [String]
346
+ # @param initheader [Hash]
347
+ # @param dest [nil]
348
+ #
349
+ #
350
+ # @return [Net::HTTPResponse]
351
+ #
352
+ # @see https://docs.ruby-lang.org/en/trunk/Net/HTTP.html
357
353
  def put(path, data, initheader = nil, dest = nil, &block)
358
354
  send_entity(path, data, initheader, dest, Put, &block)
359
355
  end
data/lib/crapi/errors.rb CHANGED
@@ -1,16 +1,16 @@
1
- module Crapi
2
- ## The base Error class for all {Crapi}-related issues.
3
- ##
1
+ module CrAPI
2
+ # The base Error class for all {CrAPI}-related issues.
3
+ #
4
4
  class Error < ::StandardError
5
5
  end
6
6
 
7
- ## An error relating to missing, invalid, or incompatible method arguments.
8
- ##
7
+ # An error relating to missing, invalid, or incompatible method arguments.
8
+ #
9
9
  class ArgumentError < Error
10
10
  end
11
11
 
12
- ## An error relating to a 4XX/5XX HTTP response code.
13
- ##
12
+ # An error relating to a 4XX/5XX HTTP response code.
13
+ #
14
14
  class BadHttpResponseError < Error
15
15
  end
16
16
  end