patient_http 1.6.1 → 1.8.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.
- checksums.yaml +4 -4
- data/ARCHITECTURE.md +18 -8
- data/CHANGELOG.md +43 -0
- data/README.md +564 -508
- data/VERSION +1 -1
- data/lib/patient_http/callback_args.rb +53 -48
- data/lib/patient_http/callback_validator.rb +11 -7
- data/lib/patient_http/class_helper.rb +6 -7
- data/lib/patient_http/client.rb +53 -26
- data/lib/patient_http/client_pool.rb +134 -39
- data/lib/patient_http/completion_executor.rb +20 -20
- data/lib/patient_http/configuration.rb +405 -119
- data/lib/patient_http/connection_endpoint.rb +150 -0
- data/lib/patient_http/encryptor.rb +28 -18
- data/lib/patient_http/error.rb +24 -18
- data/lib/patient_http/external_storage.rb +42 -38
- data/lib/patient_http/http_error.rb +30 -26
- data/lib/patient_http/http_headers.rb +35 -29
- data/lib/patient_http/immediate_retries.rb +98 -0
- data/lib/patient_http/inline_task_handler.rb +15 -10
- data/lib/patient_http/lifecycle_manager.rb +39 -40
- data/lib/patient_http/outgoing_request.rb +25 -23
- data/lib/patient_http/payload.rb +28 -26
- data/lib/patient_http/payload_store/active_record_store.rb +31 -34
- data/lib/patient_http/payload_store/base.rb +42 -46
- data/lib/patient_http/payload_store/file_store.rb +22 -26
- data/lib/patient_http/payload_store/redis_store.rb +28 -34
- data/lib/patient_http/payload_store/s3_store.rb +25 -28
- data/lib/patient_http/payload_store.rb +2 -0
- data/lib/patient_http/processor.rb +111 -79
- data/lib/patient_http/processor_observer.rb +65 -59
- data/lib/patient_http/rails/engine.rb +13 -8
- data/lib/patient_http/redirect_error.rb +50 -41
- data/lib/patient_http/redirect_helper.rb +38 -38
- data/lib/patient_http/request.rb +117 -46
- data/lib/patient_http/request_error.rb +47 -42
- data/lib/patient_http/request_helper.rb +178 -119
- data/lib/patient_http/request_preparer.rb +13 -10
- data/lib/patient_http/request_task.rb +115 -84
- data/lib/patient_http/request_template.rb +119 -64
- data/lib/patient_http/response.rb +58 -52
- data/lib/patient_http/response_reader.rb +166 -118
- data/lib/patient_http/secret_manager.rb +34 -30
- data/lib/patient_http/secret_reference.rb +33 -26
- data/lib/patient_http/synchronous_executor.rb +84 -95
- data/lib/patient_http/task_handler.rb +23 -19
- data/lib/patient_http/time_helper.rb +8 -8
- data/lib/patient_http.rb +327 -186
- data/patient_http.gemspec +3 -2
- metadata +21 -5
|
@@ -1,57 +1,77 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module PatientHttp
|
|
4
|
-
# A
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# A {Request} with the callback service and the task handler that the
|
|
5
|
+
# processor needs to run it. The task tracks the request from enqueue to
|
|
6
|
+
# completion, and delivers the result through its task handler.
|
|
7
|
+
#
|
|
8
|
+
# @example Create a task and enqueue it
|
|
9
|
+
# task = PatientHttp::RequestTask.new(
|
|
10
|
+
# request: PatientHttp::Request.new(:get, "https://api.example.com/users/123"),
|
|
11
|
+
# task_handler: MyTaskHandler.new("job-123"),
|
|
12
|
+
# callback: "FetchUserCallback",
|
|
13
|
+
# callback_args: {user_id: 123}
|
|
14
|
+
# )
|
|
15
|
+
# processor.enqueue(task)
|
|
7
16
|
class RequestTask
|
|
8
17
|
include TimeHelper
|
|
9
18
|
|
|
10
|
-
#
|
|
19
|
+
# The headers that are removed on a cross-origin redirect.
|
|
11
20
|
SENSITIVE_HEADERS = %w[authorization cookie].freeze
|
|
12
21
|
|
|
13
|
-
#
|
|
22
|
+
# The headers that describe a request body. They're removed when a redirect
|
|
23
|
+
# drops the body.
|
|
14
24
|
BODY_HEADERS = %w[content-type content-length content-encoding content-language content-location].freeze
|
|
15
25
|
|
|
16
|
-
# @return [String]
|
|
26
|
+
# @return [String] The unique task ID. A task that follows a redirect has
|
|
27
|
+
# the ID of the original task with a suffix.
|
|
17
28
|
attr_reader :id
|
|
18
29
|
|
|
19
|
-
# @return [Request] The HTTP request
|
|
30
|
+
# @return [Request] The HTTP request.
|
|
20
31
|
attr_reader :request
|
|
21
32
|
|
|
22
|
-
# @return [TaskHandler] The handler
|
|
33
|
+
# @return [TaskHandler] The task handler that delivers the result.
|
|
23
34
|
attr_reader :task_handler
|
|
24
35
|
|
|
25
|
-
# @return [String]
|
|
36
|
+
# @return [String] The callback service class name.
|
|
26
37
|
attr_reader :callback
|
|
27
38
|
|
|
28
|
-
# @return [Hash]
|
|
39
|
+
# @return [Hash] The callback arguments for the {Response} or {Error}. Never
|
|
40
|
+
# `nil`.
|
|
29
41
|
attr_reader :callback_args
|
|
30
42
|
|
|
31
|
-
# @return [Boolean] Whether
|
|
43
|
+
# @return [Boolean] Whether non-2xx responses go to the `on_error` callback
|
|
44
|
+
# as an {HttpError}.
|
|
32
45
|
attr_reader :raise_error_responses
|
|
33
46
|
|
|
34
|
-
# @return [Array<String>] URLs
|
|
47
|
+
# @return [Array<String>] The URLs of the redirects that were followed.
|
|
35
48
|
attr_reader :redirects
|
|
36
49
|
|
|
37
|
-
# @return [Response, nil] The HTTP response,
|
|
50
|
+
# @return [Response, nil] The HTTP response, after the request succeeds.
|
|
38
51
|
attr_reader :response
|
|
39
52
|
|
|
40
|
-
# @return [Exception, nil] The error,
|
|
53
|
+
# @return [Exception, nil] The error, after the request fails.
|
|
41
54
|
attr_reader :error
|
|
42
55
|
|
|
43
|
-
#
|
|
56
|
+
# Creates a task.
|
|
44
57
|
#
|
|
45
|
-
# @param request [Request] The HTTP request
|
|
46
|
-
# @param task_handler [TaskHandler] The handler
|
|
47
|
-
#
|
|
48
|
-
# @param
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
# @param
|
|
53
|
-
#
|
|
54
|
-
# @param
|
|
58
|
+
# @param request [Request] The HTTP request.
|
|
59
|
+
# @param task_handler [TaskHandler] The task handler that delivers the
|
|
60
|
+
# result.
|
|
61
|
+
# @param callback [String, Class] The callback service class, or its name.
|
|
62
|
+
# @param callback_args [Hash] The JSON-compatible arguments to pass to the
|
|
63
|
+
# callback. The callback reads them from `response.callback_args` or
|
|
64
|
+
# `error.callback_args`.
|
|
65
|
+
# @param raise_error_responses [Boolean] Whether non-2xx responses go to the
|
|
66
|
+
# `on_error` callback as an {HttpError}.
|
|
67
|
+
# @param redirects [Array<String>] The URLs of the redirects that were
|
|
68
|
+
# followed.
|
|
69
|
+
# @param id [String, nil] The unique task ID. If `nil`, a new UUID is
|
|
70
|
+
# generated.
|
|
71
|
+
# @param default_max_redirects [Integer] The maximum number of redirects to
|
|
72
|
+
# follow if the request doesn't set one.
|
|
73
|
+
# @raise [ArgumentError] If a required argument is missing, or if the
|
|
74
|
+
# callback service or callback arguments aren't valid.
|
|
55
75
|
def initialize(
|
|
56
76
|
request:,
|
|
57
77
|
task_handler:,
|
|
@@ -83,74 +103,81 @@ module PatientHttp
|
|
|
83
103
|
CallbackValidator.validate!(@callback)
|
|
84
104
|
end
|
|
85
105
|
|
|
86
|
-
#
|
|
106
|
+
# Records the time that the task was enqueued.
|
|
107
|
+
#
|
|
87
108
|
# @return [void]
|
|
88
109
|
def enqueued!
|
|
89
110
|
@enqueued_at = monotonic_time
|
|
90
111
|
end
|
|
91
112
|
|
|
92
|
-
#
|
|
113
|
+
# Records the time that the request started.
|
|
114
|
+
#
|
|
93
115
|
# @return [void]
|
|
94
116
|
def started!
|
|
95
117
|
@started_at = monotonic_time
|
|
96
118
|
end
|
|
97
119
|
|
|
98
|
-
#
|
|
99
|
-
#
|
|
100
|
-
# balanced when a task is re-enqueued during shutdown.
|
|
120
|
+
# Returns whether the request started. The processor uses this value to
|
|
121
|
+
# send `request_end` to observers only for tasks that got `request_start`.
|
|
101
122
|
#
|
|
102
|
-
# @return [Boolean]
|
|
123
|
+
# @return [Boolean] `true` if {#started!} was called.
|
|
103
124
|
def started?
|
|
104
125
|
!@started_at.nil?
|
|
105
126
|
end
|
|
106
127
|
|
|
107
|
-
# Returns the
|
|
128
|
+
# Returns the time that the task was enqueued.
|
|
108
129
|
#
|
|
109
|
-
# @return [Time, nil] The
|
|
130
|
+
# @return [Time, nil] The time, or `nil` if the task isn't enqueued.
|
|
110
131
|
def enqueued_at
|
|
111
132
|
wall_clock_time(@enqueued_at) if @enqueued_at
|
|
112
133
|
end
|
|
113
134
|
|
|
114
|
-
# Returns the
|
|
135
|
+
# Returns the time that the request started.
|
|
115
136
|
#
|
|
116
|
-
# @return [Time, nil] The
|
|
137
|
+
# @return [Time, nil] The time, or `nil` if the request didn't start.
|
|
117
138
|
def started_at
|
|
118
139
|
wall_clock_time(@started_at) if @started_at
|
|
119
140
|
end
|
|
120
141
|
|
|
121
|
-
# Returns the
|
|
142
|
+
# Returns the time that the request finished.
|
|
122
143
|
#
|
|
123
|
-
# @return [Time, nil] The
|
|
144
|
+
# @return [Time, nil] The time, or `nil` if the request didn't finish.
|
|
124
145
|
def completed_at
|
|
125
146
|
wall_clock_time(@completed_at) if @completed_at
|
|
126
147
|
end
|
|
127
148
|
|
|
128
|
-
#
|
|
129
|
-
#
|
|
149
|
+
# Returns the time that the task waited in the queue before the request
|
|
150
|
+
# started.
|
|
151
|
+
#
|
|
152
|
+
# @return [Float, nil] The duration in seconds, or `nil` if the task isn't
|
|
153
|
+
# enqueued.
|
|
130
154
|
def enqueued_duration
|
|
131
155
|
return nil unless @enqueued_at
|
|
132
156
|
|
|
133
157
|
(@started_at || monotonic_time) - @enqueued_at
|
|
134
158
|
end
|
|
135
159
|
|
|
136
|
-
#
|
|
137
|
-
#
|
|
160
|
+
# Returns the time that the request ran.
|
|
161
|
+
#
|
|
162
|
+
# @return [Float, nil] The duration in seconds, or `nil` if the request
|
|
163
|
+
# didn't start.
|
|
138
164
|
def duration
|
|
139
165
|
return nil unless @started_at
|
|
140
166
|
|
|
141
167
|
((@completed_at || monotonic_time) - @started_at).round(9)
|
|
142
168
|
end
|
|
143
169
|
|
|
144
|
-
# Re-
|
|
145
|
-
#
|
|
170
|
+
# Re-enqueues the original job through the task handler.
|
|
171
|
+
#
|
|
172
|
+
# @return [String] The new job ID.
|
|
146
173
|
def retry
|
|
147
174
|
@task_handler.retry
|
|
148
175
|
end
|
|
149
176
|
|
|
150
|
-
#
|
|
151
|
-
#
|
|
177
|
+
# Records the response, and delivers it through the task handler. The
|
|
178
|
+
# response can have an HTTP error status (4xx or 5xx).
|
|
152
179
|
#
|
|
153
|
-
# @param response [Response]
|
|
180
|
+
# @param response [Response] The HTTP response.
|
|
154
181
|
# @return [void]
|
|
155
182
|
def completed!(response)
|
|
156
183
|
@completed_at = monotonic_time
|
|
@@ -159,9 +186,10 @@ module PatientHttp
|
|
|
159
186
|
@task_handler.on_complete(response, @callback)
|
|
160
187
|
end
|
|
161
188
|
|
|
162
|
-
#
|
|
189
|
+
# Records the error, and delivers it through the task handler. An exception
|
|
190
|
+
# that isn't an {Error} is wrapped in a {RequestError}.
|
|
163
191
|
#
|
|
164
|
-
# @param exception [Exception]
|
|
192
|
+
# @param exception [Exception] The error.
|
|
165
193
|
# @return [void]
|
|
166
194
|
def error!(exception)
|
|
167
195
|
@completed_at = monotonic_time
|
|
@@ -182,45 +210,45 @@ module PatientHttp
|
|
|
182
210
|
@task_handler.on_error(wrapped_error, @callback)
|
|
183
211
|
end
|
|
184
212
|
|
|
185
|
-
#
|
|
186
|
-
#
|
|
213
|
+
# Returns whether the server sent a response. The response can have an HTTP
|
|
214
|
+
# error status (4xx or 5xx).
|
|
187
215
|
#
|
|
188
|
-
# @return [Boolean]
|
|
216
|
+
# @return [Boolean] `true` if a response was received.
|
|
189
217
|
def success?
|
|
190
218
|
!@response.nil?
|
|
191
219
|
end
|
|
192
220
|
|
|
193
|
-
#
|
|
221
|
+
# Returns whether the request raised an error.
|
|
194
222
|
#
|
|
195
|
-
# @return [Boolean]
|
|
223
|
+
# @return [Boolean] `true` if the request failed.
|
|
196
224
|
def error?
|
|
197
225
|
!@error.nil?
|
|
198
226
|
end
|
|
199
227
|
|
|
200
|
-
# Returns the maximum number of redirects to follow.
|
|
201
|
-
#
|
|
228
|
+
# Returns the maximum number of redirects to follow. The request value
|
|
229
|
+
# applies if it's set. Otherwise, the default applies.
|
|
202
230
|
#
|
|
203
|
-
# @return [Integer] maximum number of redirects
|
|
231
|
+
# @return [Integer] The maximum number of redirects.
|
|
204
232
|
def max_redirects
|
|
205
233
|
request.max_redirects || @default_max_redirects
|
|
206
234
|
end
|
|
207
235
|
|
|
208
|
-
#
|
|
236
|
+
# Creates a task that follows a redirect.
|
|
209
237
|
#
|
|
210
|
-
# The HTTP method follows RFC 9110
|
|
211
|
-
# changes
|
|
212
|
-
#
|
|
213
|
-
#
|
|
238
|
+
# The HTTP method follows RFC 9110. A 301 or 302 changes POST to GET. A 303
|
|
239
|
+
# changes all methods except GET and HEAD to GET. A 300, 307, or 308 keeps
|
|
240
|
+
# the method. When the method changes, the body and the headers that
|
|
241
|
+
# describe it are removed.
|
|
214
242
|
#
|
|
215
|
-
#
|
|
216
|
-
#
|
|
217
|
-
# headers and preprocessors are removed
|
|
243
|
+
# The headers named in the request's `redirect_strip_headers` or in
|
|
244
|
+
# `strip_headers` are removed. On a cross-origin redirect, the
|
|
245
|
+
# `Authorization` and `Cookie` headers and the preprocessors are removed.
|
|
218
246
|
#
|
|
219
|
-
# @param location [String] The
|
|
220
|
-
# @param status [Integer] The HTTP status
|
|
221
|
-
# @param strip_headers [Array<String>]
|
|
222
|
-
#
|
|
223
|
-
# @return [RequestTask]
|
|
247
|
+
# @param location [String] The URL from the `Location` header.
|
|
248
|
+
# @param status [Integer] The HTTP status of the redirect response.
|
|
249
|
+
# @param strip_headers [Array<String>] More header names to remove, usually
|
|
250
|
+
# from the {Configuration}.
|
|
251
|
+
# @return [RequestTask] The task for the redirect.
|
|
224
252
|
def redirect_task(location:, status:, strip_headers: [])
|
|
225
253
|
redirect_method = RedirectHelper.redirect_method(request.http_method, status)
|
|
226
254
|
method_changed = (redirect_method != request.http_method)
|
|
@@ -246,6 +274,8 @@ module PatientHttp
|
|
|
246
274
|
headers: redirect_headers,
|
|
247
275
|
body: redirect_body,
|
|
248
276
|
timeout: request.timeout,
|
|
277
|
+
read_timeout: request.read_timeout,
|
|
278
|
+
max_response_size: request.max_response_size,
|
|
249
279
|
max_redirects: request.max_redirects,
|
|
250
280
|
follow_method_changing_redirects: request.follow_method_changing_redirects,
|
|
251
281
|
redirect_strip_headers: request.redirect_strip_headers,
|
|
@@ -268,12 +298,12 @@ module PatientHttp
|
|
|
268
298
|
)
|
|
269
299
|
end
|
|
270
300
|
|
|
271
|
-
#
|
|
301
|
+
# Builds a {Response} for this task.
|
|
272
302
|
#
|
|
273
|
-
# @param status [Integer] HTTP status code
|
|
274
|
-
# @param headers [Hash]
|
|
275
|
-
# @param body [String, nil]
|
|
276
|
-
# @return [Response]
|
|
303
|
+
# @param status [Integer] The HTTP status code.
|
|
304
|
+
# @param headers [Hash] The response headers.
|
|
305
|
+
# @param body [String, nil] The response body.
|
|
306
|
+
# @return [Response] The response.
|
|
277
307
|
# @api private
|
|
278
308
|
def build_response(status:, headers:, body:)
|
|
279
309
|
original_id = id.split("/").first
|
|
@@ -291,21 +321,22 @@ module PatientHttp
|
|
|
291
321
|
)
|
|
292
322
|
end
|
|
293
323
|
|
|
294
|
-
#
|
|
295
|
-
#
|
|
324
|
+
# Returns the ID of the first task, before any redirects. Use it to track a
|
|
325
|
+
# request across its redirect tasks.
|
|
296
326
|
#
|
|
297
|
-
# @return [String]
|
|
327
|
+
# @return [String] The original task ID.
|
|
298
328
|
def original_id
|
|
299
329
|
id.split("/").first
|
|
300
330
|
end
|
|
301
331
|
|
|
302
332
|
private
|
|
303
333
|
|
|
304
|
-
#
|
|
334
|
+
# Returns whether two URLs have different origins. The origin is the
|
|
335
|
+
# scheme, host, and port.
|
|
305
336
|
#
|
|
306
|
-
# @param original_url [String] The original request URL
|
|
307
|
-
# @param target_url [String] The redirect
|
|
308
|
-
# @return [Boolean] true if the origins
|
|
337
|
+
# @param original_url [String] The original request URL.
|
|
338
|
+
# @param target_url [String] The redirect URL.
|
|
339
|
+
# @return [Boolean] `true` if the origins are different.
|
|
309
340
|
def cross_origin?(original_url, target_url)
|
|
310
341
|
original = URI.parse(original_url)
|
|
311
342
|
target = URI.parse(target_url)
|
|
@@ -315,10 +346,10 @@ module PatientHttp
|
|
|
315
346
|
original.port != target.port
|
|
316
347
|
end
|
|
317
348
|
|
|
318
|
-
#
|
|
349
|
+
# Resolves a redirect URL. A relative URL is joined with the request URL.
|
|
319
350
|
#
|
|
320
|
-
# @param location [String] The Location header value
|
|
321
|
-
# @return [String] The
|
|
351
|
+
# @param location [String] The `Location` header value.
|
|
352
|
+
# @return [String] The absolute URL.
|
|
322
353
|
def resolve_redirect_url(location)
|
|
323
354
|
base_uri = URI.parse(request.url)
|
|
324
355
|
redirect_uri = URI.parse(location)
|
|
@@ -1,67 +1,109 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module PatientHttp
|
|
4
|
-
#
|
|
4
|
+
# Builds requests that share settings, such as a base URL, headers, and a
|
|
5
|
+
# timeout. Use a template to make many requests to the same API.
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
7
|
+
# The template joins each path with the base URL, and merges the headers and
|
|
8
|
+
# query parameters of each request with its own.
|
|
8
9
|
#
|
|
9
|
-
# @example
|
|
10
|
+
# @example Build a request
|
|
10
11
|
# template = PatientHttp::RequestTemplate.new(
|
|
11
12
|
# base_url: "https://api.example.com",
|
|
12
13
|
# headers: {"Authorization" => "Bearer token"},
|
|
13
14
|
# timeout: 60
|
|
14
15
|
# )
|
|
15
16
|
# request = template.get("/users/123")
|
|
16
|
-
#
|
|
17
|
-
# The RequestTemplate handles building HTTP requests with proper URL joining, header merging,
|
|
18
|
-
# and parameter encoding.
|
|
17
|
+
# PatientHttp.execute(request: request, callback: FetchUserCallback)
|
|
19
18
|
class RequestTemplate
|
|
20
|
-
# @return [String, URI::HTTP, nil]
|
|
19
|
+
# @return [String, URI::HTTP, nil] The base URL that relative paths are
|
|
20
|
+
# joined with.
|
|
21
21
|
attr_accessor :base_url
|
|
22
22
|
|
|
23
|
-
# @return [HttpHeaders]
|
|
23
|
+
# @return [HttpHeaders] The default headers for all requests.
|
|
24
24
|
attr_accessor :headers
|
|
25
25
|
|
|
26
|
-
# @return [
|
|
26
|
+
# @return [Numeric, nil] The default request timeout in seconds. If `nil`,
|
|
27
|
+
# the configured `request_timeout` applies.
|
|
27
28
|
attr_accessor :timeout
|
|
28
29
|
|
|
29
|
-
#
|
|
30
|
+
# @return [Numeric, nil] The default read timeout in seconds. If `nil`, the
|
|
31
|
+
# configured `read_timeout` applies.
|
|
32
|
+
attr_accessor :read_timeout
|
|
33
|
+
|
|
34
|
+
# @return [Integer, nil] The default maximum response body size in bytes. If
|
|
35
|
+
# `nil`, the configured `max_response_size` applies.
|
|
36
|
+
attr_accessor :max_response_size
|
|
37
|
+
|
|
38
|
+
# Creates a template.
|
|
30
39
|
#
|
|
31
|
-
# @param base_url [String, URI::HTTP, nil]
|
|
32
|
-
#
|
|
33
|
-
# @param
|
|
34
|
-
# @param
|
|
35
|
-
# @param
|
|
36
|
-
#
|
|
37
|
-
# @param
|
|
38
|
-
|
|
40
|
+
# @param base_url [String, URI::HTTP, nil] The base URL that relative paths
|
|
41
|
+
# are joined with.
|
|
42
|
+
# @param headers [Hash] The default headers for all requests.
|
|
43
|
+
# @param params [Hash, nil] The default query parameters for all requests.
|
|
44
|
+
# @param timeout [Numeric, nil] The default request timeout in seconds. If
|
|
45
|
+
# `nil`, the configured `request_timeout` applies.
|
|
46
|
+
# @param read_timeout [Numeric, nil] The default maximum number of seconds to
|
|
47
|
+
# wait for data from the server. If `nil`, the configured `read_timeout`
|
|
48
|
+
# applies.
|
|
49
|
+
# @param max_response_size [Integer, nil] The default maximum response body
|
|
50
|
+
# size in bytes. If `nil`, the configured `max_response_size` applies.
|
|
51
|
+
# @param preprocessors [String, Symbol, Array<String, Symbol>, nil] The names
|
|
52
|
+
# of the default preprocessors for all requests.
|
|
53
|
+
# @param processor [String, Symbol, nil] The name of the default processor for
|
|
54
|
+
# all requests.
|
|
55
|
+
def initialize(
|
|
56
|
+
base_url: nil,
|
|
57
|
+
headers: {},
|
|
58
|
+
params: nil,
|
|
59
|
+
timeout: nil,
|
|
60
|
+
read_timeout: nil,
|
|
61
|
+
max_response_size: nil,
|
|
62
|
+
preprocessors: nil,
|
|
63
|
+
processor: nil
|
|
64
|
+
)
|
|
39
65
|
@base_url = base_url
|
|
40
66
|
@headers = HttpHeaders.new(headers)
|
|
41
67
|
@params = params
|
|
42
68
|
@timeout = timeout
|
|
69
|
+
@read_timeout = read_timeout
|
|
70
|
+
@max_response_size = max_response_size
|
|
43
71
|
@preprocessors = preprocessors
|
|
44
72
|
@processor = processor
|
|
45
73
|
end
|
|
46
74
|
|
|
47
|
-
#
|
|
75
|
+
# Builds a request.
|
|
48
76
|
#
|
|
49
|
-
# @param method [Symbol] HTTP method
|
|
50
|
-
#
|
|
51
|
-
# @param
|
|
52
|
-
#
|
|
53
|
-
# @param
|
|
54
|
-
# @param
|
|
55
|
-
#
|
|
56
|
-
# @param
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
77
|
+
# @param method [Symbol] The HTTP method: `:get`, `:head`, `:post`, `:put`,
|
|
78
|
+
# `:patch`, `:delete`, or `:query`.
|
|
79
|
+
# @param uri [String, URI::HTTP] The URL. A relative path is joined with the
|
|
80
|
+
# base URL.
|
|
81
|
+
# @param body [String, nil] The request body.
|
|
82
|
+
# @param json [Object, nil] An object to send as a JSON body. Can't be combined
|
|
83
|
+
# with `body`.
|
|
84
|
+
# @param headers [Hash, nil] The headers to merge with the template headers.
|
|
85
|
+
# @param params [Hash, nil] The query parameters to merge with the template
|
|
86
|
+
# parameters.
|
|
87
|
+
# @param timeout [Numeric, nil] The request timeout in seconds. Overrides the
|
|
88
|
+
# template timeout.
|
|
89
|
+
# @param read_timeout [Numeric, nil] The maximum number of seconds to wait for
|
|
90
|
+
# data from the server. Overrides the template read timeout.
|
|
91
|
+
# @param max_response_size [Integer, nil] The maximum response body size in
|
|
92
|
+
# bytes. Overrides the template value.
|
|
93
|
+
# @param max_redirects [Integer, nil] The maximum number of redirects to
|
|
94
|
+
# follow. If `0`, redirects aren't followed. If `nil`, the configuration
|
|
95
|
+
# value applies.
|
|
96
|
+
# @param follow_method_changing_redirects [Boolean, nil] Whether to follow a
|
|
97
|
+
# redirect that changes the HTTP method. If `nil`, the configuration value
|
|
98
|
+
# applies.
|
|
99
|
+
# @param redirect_strip_headers [String, Array<String>, nil] The names of headers
|
|
100
|
+
# to remove from redirected requests, in addition to the configured names.
|
|
101
|
+
# Names are case insensitive.
|
|
102
|
+
# @param preprocessors [String, Symbol, Array<String, Symbol>, nil] The names of
|
|
103
|
+
# the preprocessors for the request. Overrides the template preprocessors.
|
|
104
|
+
# @param processor [String, Symbol, nil] The name of the processor for the
|
|
105
|
+
# request. Overrides the template processor.
|
|
106
|
+
# @return [Request] The request.
|
|
65
107
|
def request(
|
|
66
108
|
method,
|
|
67
109
|
uri,
|
|
@@ -70,6 +112,9 @@ module PatientHttp
|
|
|
70
112
|
headers: nil,
|
|
71
113
|
params: nil,
|
|
72
114
|
timeout: nil,
|
|
115
|
+
read_timeout: nil,
|
|
116
|
+
max_response_size: nil,
|
|
117
|
+
max_redirects: nil,
|
|
73
118
|
follow_method_changing_redirects: nil,
|
|
74
119
|
redirect_strip_headers: nil,
|
|
75
120
|
preprocessors: nil,
|
|
@@ -89,6 +134,9 @@ module PatientHttp
|
|
|
89
134
|
json: json,
|
|
90
135
|
params: merged_params,
|
|
91
136
|
timeout: timeout || @timeout,
|
|
137
|
+
read_timeout: read_timeout || @read_timeout,
|
|
138
|
+
max_response_size: max_response_size || @max_response_size,
|
|
139
|
+
max_redirects: max_redirects,
|
|
92
140
|
follow_method_changing_redirects: follow_method_changing_redirects,
|
|
93
141
|
redirect_strip_headers: redirect_strip_headers,
|
|
94
142
|
preprocessors: preprocessors || @preprocessors,
|
|
@@ -96,65 +144,72 @@ module PatientHttp
|
|
|
96
144
|
)
|
|
97
145
|
end
|
|
98
146
|
|
|
99
|
-
#
|
|
147
|
+
# Builds a GET request.
|
|
100
148
|
#
|
|
101
|
-
# @param uri [String, URI::HTTP]
|
|
102
|
-
#
|
|
103
|
-
# @
|
|
149
|
+
# @param uri [String, URI::HTTP] The URL. A relative path is joined with the
|
|
150
|
+
# base URL.
|
|
151
|
+
# @param kwargs [Hash] The request options. See {#request}.
|
|
152
|
+
# @return [Request] The request.
|
|
104
153
|
def get(uri, **kwargs)
|
|
105
154
|
request(:get, uri, **kwargs)
|
|
106
155
|
end
|
|
107
156
|
|
|
108
|
-
#
|
|
157
|
+
# Builds a HEAD request.
|
|
109
158
|
#
|
|
110
|
-
# @param uri [String, URI::HTTP]
|
|
111
|
-
#
|
|
112
|
-
# @
|
|
159
|
+
# @param uri [String, URI::HTTP] The URL. A relative path is joined with the
|
|
160
|
+
# base URL.
|
|
161
|
+
# @param kwargs [Hash] The request options. See {#request}.
|
|
162
|
+
# @return [Request] The request.
|
|
113
163
|
def head(uri, **kwargs)
|
|
114
164
|
request(:head, uri, **kwargs)
|
|
115
165
|
end
|
|
116
166
|
|
|
117
|
-
#
|
|
167
|
+
# Builds a POST request.
|
|
118
168
|
#
|
|
119
|
-
# @param uri [String, URI::HTTP]
|
|
120
|
-
#
|
|
121
|
-
# @
|
|
169
|
+
# @param uri [String, URI::HTTP] The URL. A relative path is joined with the
|
|
170
|
+
# base URL.
|
|
171
|
+
# @param kwargs [Hash] The request options. See {#request}.
|
|
172
|
+
# @return [Request] The request.
|
|
122
173
|
def post(uri, **kwargs)
|
|
123
174
|
request(:post, uri, **kwargs)
|
|
124
175
|
end
|
|
125
176
|
|
|
126
|
-
#
|
|
177
|
+
# Builds a PUT request.
|
|
127
178
|
#
|
|
128
|
-
# @param uri [String, URI::HTTP]
|
|
129
|
-
#
|
|
130
|
-
# @
|
|
179
|
+
# @param uri [String, URI::HTTP] The URL. A relative path is joined with the
|
|
180
|
+
# base URL.
|
|
181
|
+
# @param kwargs [Hash] The request options. See {#request}.
|
|
182
|
+
# @return [Request] The request.
|
|
131
183
|
def put(uri, **kwargs)
|
|
132
184
|
request(:put, uri, **kwargs)
|
|
133
185
|
end
|
|
134
186
|
|
|
135
|
-
#
|
|
187
|
+
# Builds a PATCH request.
|
|
136
188
|
#
|
|
137
|
-
# @param uri [String, URI::HTTP]
|
|
138
|
-
#
|
|
139
|
-
# @
|
|
189
|
+
# @param uri [String, URI::HTTP] The URL. A relative path is joined with the
|
|
190
|
+
# base URL.
|
|
191
|
+
# @param kwargs [Hash] The request options. See {#request}.
|
|
192
|
+
# @return [Request] The request.
|
|
140
193
|
def patch(uri, **kwargs)
|
|
141
194
|
request(:patch, uri, **kwargs)
|
|
142
195
|
end
|
|
143
196
|
|
|
144
|
-
#
|
|
197
|
+
# Builds a DELETE request.
|
|
145
198
|
#
|
|
146
|
-
# @param uri [String, URI::HTTP]
|
|
147
|
-
#
|
|
148
|
-
# @
|
|
199
|
+
# @param uri [String, URI::HTTP] The URL. A relative path is joined with the
|
|
200
|
+
# base URL.
|
|
201
|
+
# @param kwargs [Hash] The request options. See {#request}.
|
|
202
|
+
# @return [Request] The request.
|
|
149
203
|
def delete(uri, **kwargs)
|
|
150
204
|
request(:delete, uri, **kwargs)
|
|
151
205
|
end
|
|
152
206
|
|
|
153
|
-
#
|
|
207
|
+
# Builds a QUERY request.
|
|
154
208
|
#
|
|
155
|
-
# @param uri [String, URI::HTTP]
|
|
156
|
-
#
|
|
157
|
-
# @
|
|
209
|
+
# @param uri [String, URI::HTTP] The URL. A relative path is joined with the
|
|
210
|
+
# base URL.
|
|
211
|
+
# @param kwargs [Hash] The request options. See {#request}.
|
|
212
|
+
# @return [Request] The request.
|
|
158
213
|
def query(uri, **kwargs)
|
|
159
214
|
request(:query, uri, **kwargs)
|
|
160
215
|
end
|