crapi 0.1.3 → 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/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