berkeley_library-util 0.1.6 → 0.1.7
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/CHANGES.md +7 -0
- data/lib/berkeley_library/util/module_info.rb +1 -1
- data/lib/berkeley_library/util/uris/appender.rb +8 -0
- data/lib/berkeley_library/util/uris/requester.rb +97 -42
- data/lib/berkeley_library/util/uris.rb +14 -10
- data/spec/berkeley_library/util/uris/requester_spec.rb +106 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71143c349265481e222ad5c0330ad1f995697139d114f9b9a2615c8d9cb8ea4b
|
4
|
+
data.tar.gz: 3ad66018de9e3ff7efe0d5637c9c79ea616da7510aff3c6f8f9bc07ed83cbb59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0563b8e84cdeff86055d4423ddf57a6559c7e9a80527b643fe9cf4c10db2a62cbd8e122fc0045da56778b00ac6486ebff8ab00a5452721f385a93e9f8fc6e12
|
7
|
+
data.tar.gz: c19e2f817542e98ec80b9e05faf6bdaad821ab8f6589638c3790611de8231cd7bbf2a68f3d0a520fb7b96a8b0c16ac06685ae547ad6c5b7023468bea50ec4f01
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# 0.1.7 (2023-03-15)
|
2
|
+
|
3
|
+
- Allow passing `log: false` to `Requester` methods (and corresponding `URIs` convenience
|
4
|
+
methods) to suppress logging of each request URL and response code.
|
5
|
+
- Allow constructing `Requester` instances with delayed execution
|
6
|
+
- Fix documentation for `get_response` and `head_response` in `URIs` and `Requester`
|
7
|
+
|
1
8
|
# 0.1.6 (2023-03-09)
|
2
9
|
|
3
10
|
- Fix issue in `Requester` where query parameters would not be appended properly
|
@@ -7,7 +7,7 @@ module BerkeleyLibrary
|
|
7
7
|
SUMMARY = 'Miscellaneous Ruby utilities for the UC Berkeley Library'.freeze
|
8
8
|
DESCRIPTION = 'A collection of miscellaneous Ruby routines for the UC Berkeley Library.'.freeze
|
9
9
|
LICENSE = 'MIT'.freeze
|
10
|
-
VERSION = '0.1.
|
10
|
+
VERSION = '0.1.7'.freeze
|
11
11
|
HOMEPAGE = 'https://github.com/BerkeleyLibrary/util'.freeze
|
12
12
|
end
|
13
13
|
end
|
@@ -39,6 +39,14 @@ module BerkeleyLibrary
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
# Returns the new URI as a string.
|
43
|
+
#
|
44
|
+
# @return [String] a new URI appending the joined path elements, as a string.
|
45
|
+
# @raise URI::InvalidComponentError if appending the specified elements would create an invalid URI
|
46
|
+
def to_url_str
|
47
|
+
to_uri.to_s
|
48
|
+
end
|
49
|
+
|
42
50
|
private
|
43
51
|
|
44
52
|
def handle_element(element, elem_index)
|
@@ -6,19 +6,23 @@ require 'berkeley_library/logging'
|
|
6
6
|
module BerkeleyLibrary
|
7
7
|
module Util
|
8
8
|
module URIs
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
class Requester
|
10
|
+
include BerkeleyLibrary::Logging
|
11
|
+
|
12
|
+
# ------------------------------------------------------------
|
13
|
+
# Class methods
|
12
14
|
|
15
|
+
class << self
|
13
16
|
# Performs a GET request and returns the response body as a string.
|
14
17
|
#
|
15
18
|
# @param uri [URI, String] the URI to GET
|
16
19
|
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
17
20
|
# @param headers [Hash] the request headers.
|
18
21
|
# @return [String] the body as a string.
|
22
|
+
# @param log [Boolean] whether to log each request URL and response code
|
19
23
|
# @raise [RestClient::Exception] in the event of an unsuccessful request.
|
20
|
-
def get(uri, params: {}, headers: {})
|
21
|
-
resp = make_request(:get, uri, params, headers)
|
24
|
+
def get(uri, params: {}, headers: {}, log: true)
|
25
|
+
resp = make_request(:get, uri, params, headers, log)
|
22
26
|
resp.body
|
23
27
|
end
|
24
28
|
|
@@ -29,9 +33,10 @@ module BerkeleyLibrary
|
|
29
33
|
# @param uri [URI, String] the URI to HEAD
|
30
34
|
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
31
35
|
# @param headers [Hash] the request headers.
|
36
|
+
# @param log [Boolean] whether to log each request URL and response code
|
32
37
|
# @return [Integer] the response code as an integer.
|
33
|
-
def head(uri, params: {}, headers: {})
|
34
|
-
head_response(uri, params: params, headers: headers).code
|
38
|
+
def head(uri, params: {}, headers: {}, log: true)
|
39
|
+
head_response(uri, params: params, headers: headers, log: log).code
|
35
40
|
end
|
36
41
|
|
37
42
|
# Performs a GET request and returns the response, even in the event of
|
@@ -40,9 +45,10 @@ module BerkeleyLibrary
|
|
40
45
|
# @param uri [URI, String] the URI to GET
|
41
46
|
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
42
47
|
# @param headers [Hash] the request headers.
|
48
|
+
# @param log [Boolean] whether to log each request URL and response code
|
43
49
|
# @return [RestClient::Response] the body as a string.
|
44
|
-
def get_response(uri, params: {}, headers: {})
|
45
|
-
make_request(:get, uri, params, headers)
|
50
|
+
def get_response(uri, params: {}, headers: {}, log: true)
|
51
|
+
make_request(:get, uri, params, headers, log)
|
46
52
|
rescue RestClient::Exception => e
|
47
53
|
e.response
|
48
54
|
end
|
@@ -53,56 +59,105 @@ module BerkeleyLibrary
|
|
53
59
|
# @param uri [URI, String] the URI to HEAD
|
54
60
|
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
55
61
|
# @param headers [Hash] the request headers.
|
56
|
-
# @
|
57
|
-
|
58
|
-
|
62
|
+
# @param log [Boolean] whether to log each request URL and response code
|
63
|
+
# @return [RestClient::Response] the response
|
64
|
+
def head_response(uri, params: {}, headers: {}, log: true)
|
65
|
+
make_request(:head, uri, params, headers, log)
|
59
66
|
rescue RestClient::Exception => e
|
60
67
|
e.response
|
61
68
|
end
|
62
69
|
|
63
70
|
private
|
64
71
|
|
65
|
-
|
66
|
-
|
67
|
-
url_str = url_str_with_params(uri, params)
|
68
|
-
req_resp_or_raise(method, url_str, headers)
|
72
|
+
def make_request(method, url, params, headers, log)
|
73
|
+
Requester.new(method, url, params: params, headers: headers, log: log).make_request
|
69
74
|
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# ------------------------------------------------------------
|
78
|
+
# Constants
|
79
|
+
|
80
|
+
SUPPORTED_METHODS = %i[get head].freeze
|
70
81
|
|
71
|
-
|
72
|
-
|
82
|
+
# ------------------------------------------------------------
|
83
|
+
# Attributes
|
73
84
|
|
74
|
-
|
75
|
-
ee << uri
|
76
|
-
next if params.empty?
|
85
|
+
attr_reader :method, :url_str, :headers, :log
|
77
86
|
|
78
|
-
|
79
|
-
|
80
|
-
end
|
87
|
+
# ------------------------------------------------------------
|
88
|
+
# Initializer
|
81
89
|
|
82
|
-
|
83
|
-
|
90
|
+
# Initializes a new Requester.
|
91
|
+
#
|
92
|
+
# @param method [:get, :head] the HTTP method to use
|
93
|
+
# @param url [String, URI] the URL or URI to request
|
94
|
+
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
95
|
+
# @param headers [Hash] the request headers.
|
96
|
+
# @param log [Boolean] whether to log each request URL and response code
|
97
|
+
# @raise URI::InvalidURIError if the specified URL is invalid
|
98
|
+
def initialize(method, url, params: {}, headers: {}, log: true)
|
99
|
+
raise ArgumentError, "#{method} not supported" unless SUPPORTED_METHODS.include?(method)
|
100
|
+
raise ArgumentError, 'url cannot be nil' unless (uri = Validator.uri_or_nil(url))
|
101
|
+
|
102
|
+
@method = method
|
103
|
+
@url_str = url_str_with_params(uri, params)
|
104
|
+
@headers = headers
|
105
|
+
@log = log
|
106
|
+
end
|
107
|
+
|
108
|
+
# ------------------------------------------------------------
|
109
|
+
# Public instance methods
|
110
|
+
|
111
|
+
# @return [RestClient::Response]
|
112
|
+
def make_request
|
113
|
+
execute_request.tap do |resp|
|
114
|
+
log_response(resp)
|
84
115
|
end
|
116
|
+
rescue RestClient::Exception => e
|
117
|
+
log_response(e.response)
|
118
|
+
raise
|
119
|
+
end
|
120
|
+
|
121
|
+
# ------------------------------------------------------------
|
122
|
+
# Private methods
|
85
123
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
124
|
+
private
|
125
|
+
|
126
|
+
def log_response(response)
|
127
|
+
return unless log
|
128
|
+
|
129
|
+
logger.info("#{method.to_s.upcase} #{url_str} returned #{response.code}")
|
130
|
+
end
|
131
|
+
|
132
|
+
def url_str_with_params(uri, params)
|
133
|
+
elements = [uri]
|
134
|
+
if params.any?
|
135
|
+
elements << (uri.query ? '&' : '?')
|
136
|
+
elements << URI.encode_www_form(params)
|
137
|
+
end
|
138
|
+
|
139
|
+
Appender.new(*elements).to_url_str
|
140
|
+
end
|
141
|
+
|
142
|
+
def execute_request
|
143
|
+
RestClient::Request.execute(method: method, url: url_str, headers: headers).tap do |response|
|
144
|
+
# Not all failed RestClient requests throw exceptions
|
145
|
+
raise(exception_for(response)) unless response.code == 200
|
97
146
|
end
|
147
|
+
end
|
98
148
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
149
|
+
def exception_for(resp)
|
150
|
+
status = resp.code
|
151
|
+
ex_class_for(status).new(resp, status).tap do |ex|
|
152
|
+
status_message = RestClient::STATUSES[status] || '(Unknown)'
|
153
|
+
ex.message = "#{status} #{status_message}"
|
104
154
|
end
|
105
155
|
end
|
156
|
+
|
157
|
+
def ex_class_for(status)
|
158
|
+
RestClient::Exceptions::EXCEPTIONS_MAP[status] || RestClient::RequestFailed
|
159
|
+
end
|
160
|
+
|
106
161
|
end
|
107
162
|
end
|
108
163
|
end
|
@@ -31,10 +31,11 @@ module BerkeleyLibrary
|
|
31
31
|
# @param uri [URI, String] the URI to GET
|
32
32
|
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
33
33
|
# @param headers [Hash] the request headers.
|
34
|
+
# @param log [Boolean] whether to log each request URL and response code
|
34
35
|
# @return [String] the body as a string.
|
35
36
|
# @raise [RestClient::Exception] in the event of an unsuccessful request.
|
36
|
-
def get(uri, params: {}, headers: {})
|
37
|
-
Requester.get(uri, params: params, headers: headers)
|
37
|
+
def get(uri, params: {}, headers: {}, log: true)
|
38
|
+
Requester.get(uri, params: params, headers: headers, log: log)
|
38
39
|
end
|
39
40
|
|
40
41
|
# Performs a HEAD request and returns the response status as an integer.
|
@@ -44,9 +45,10 @@ module BerkeleyLibrary
|
|
44
45
|
# @param uri [URI, String] the URI to HEAD
|
45
46
|
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
46
47
|
# @param headers [Hash] the request headers.
|
48
|
+
# @param log [Boolean] whether to log each request URL and response code
|
47
49
|
# @return [Integer] the response code as an integer.
|
48
|
-
def head(uri, params: {}, headers: {})
|
49
|
-
Requester.head(uri, params: params, headers: headers)
|
50
|
+
def head(uri, params: {}, headers: {}, log: true)
|
51
|
+
Requester.head(uri, params: params, headers: headers, log: log)
|
50
52
|
end
|
51
53
|
|
52
54
|
# Performs a GET request and returns the response, even in the event of
|
@@ -55,9 +57,10 @@ module BerkeleyLibrary
|
|
55
57
|
# @param uri [URI, String] the URI to GET
|
56
58
|
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
57
59
|
# @param headers [Hash] the request headers.
|
58
|
-
# @
|
59
|
-
|
60
|
-
|
60
|
+
# @param log [Boolean] whether to log each request URL and response code
|
61
|
+
# @return [RestClient::Response] the response
|
62
|
+
def get_response(uri, params: {}, headers: {}, log: true)
|
63
|
+
Requester.get_response(uri, params: params, headers: headers, log: log)
|
61
64
|
end
|
62
65
|
|
63
66
|
# Performs a HEAD request and returns the response, even in the event of
|
@@ -66,9 +69,10 @@ module BerkeleyLibrary
|
|
66
69
|
# @param uri [URI, String] the URI to HEAD
|
67
70
|
# @param params [Hash] the query parameters to add to the URI. (Note that the URI may already include query parameters.)
|
68
71
|
# @param headers [Hash] the request headers.
|
69
|
-
# @
|
70
|
-
|
71
|
-
|
72
|
+
# @param log [Boolean] whether to log each request URL and response code
|
73
|
+
# @return [RestClient::Response] the response
|
74
|
+
def head_response(uri, params: {}, headers: {}, log: true)
|
75
|
+
Requester.head_response(uri, params: params, headers: headers, log: log)
|
72
76
|
end
|
73
77
|
|
74
78
|
# Returns the specified URL as a URI, or `nil` if the URL is `nil`.
|
@@ -145,6 +145,112 @@ module BerkeleyLibrary
|
|
145
145
|
expect { Requester.head(nil) }.to raise_error(ArgumentError)
|
146
146
|
end
|
147
147
|
end
|
148
|
+
|
149
|
+
describe 'logging' do
|
150
|
+
attr_reader :logger
|
151
|
+
|
152
|
+
before do
|
153
|
+
@logger = instance_double(BerkeleyLibrary::Logging::Logger)
|
154
|
+
allow(BerkeleyLibrary::Logging).to receive(:logger).and_return(logger)
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'GET' do
|
158
|
+
it 'logs request URLs and response codes for successful GET requests' do
|
159
|
+
url = 'https://example.org/'
|
160
|
+
expected_body = 'Help! I am trapped in a unit test'
|
161
|
+
stub_request(:get, url).to_return(body: expected_body)
|
162
|
+
|
163
|
+
expect(logger).to receive(:info).with(/#{url}.*200/)
|
164
|
+
Requester.send(:get, url)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'can suppress logging for successful GET requests' do
|
168
|
+
url = 'https://example.org/'
|
169
|
+
expected_body = 'Help! I am trapped in a unit test'
|
170
|
+
stub_request(:get, url).to_return(body: expected_body)
|
171
|
+
|
172
|
+
expect(logger).not_to receive(:info)
|
173
|
+
Requester.send(:get, url, log: false)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'logs request URLs and response codes for failed GET requests' do
|
177
|
+
url = 'https://example.org/'
|
178
|
+
status = 500
|
179
|
+
stub_request(:get, url).to_return(status: status)
|
180
|
+
|
181
|
+
expect(logger).to receive(:info).with(/#{url}.*#{status}/)
|
182
|
+
expect { Requester.send(:get, url) }.to raise_error(RestClient::InternalServerError)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'can suppress logging for failed GET requests' do
|
186
|
+
url = 'https://example.org/'
|
187
|
+
stub_request(:get, url).to_return(status: 500)
|
188
|
+
|
189
|
+
expect(logger).not_to receive(:info)
|
190
|
+
expect { Requester.send(:get, url, log: false) }.to raise_error(RestClient::InternalServerError)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'HEAD' do
|
195
|
+
it 'logs request URLs and response codes for successful HEAD requests' do
|
196
|
+
url = 'https://example.org/'
|
197
|
+
expected_body = 'Help! I am trapped in a unit test'
|
198
|
+
stub_request(:head, url).to_return(body: expected_body)
|
199
|
+
|
200
|
+
expect(logger).to receive(:info).with(/#{url}.*200/)
|
201
|
+
Requester.send(:head, url)
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'can suppress logging for successful HEAD requests' do
|
205
|
+
url = 'https://example.org/'
|
206
|
+
expected_body = 'Help! I am trapped in a unit test'
|
207
|
+
stub_request(:head, url).to_return(body: expected_body)
|
208
|
+
|
209
|
+
expect(logger).not_to receive(:info)
|
210
|
+
Requester.send(:head, url, log: false)
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'logs request URLs and response codes for failed HEAD requests' do
|
214
|
+
url = 'https://example.org/'
|
215
|
+
status = 500
|
216
|
+
stub_request(:head, url).to_return(status: status)
|
217
|
+
|
218
|
+
expect(logger).to receive(:info).with(/#{url}.*#{status}/)
|
219
|
+
expect(Requester.send(:head, url)).to eq(status)
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'can suppress logging for failed HEAD requests' do
|
223
|
+
url = 'https://example.org/'
|
224
|
+
status = 500
|
225
|
+
stub_request(:head, url).to_return(status: status)
|
226
|
+
|
227
|
+
expect(logger).not_to receive(:info)
|
228
|
+
expect(Requester.send(:head, url, log: false)).to eq(status)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe :new do
|
234
|
+
it 'rejects invalid URIs' do
|
235
|
+
url = 'not a uri'
|
236
|
+
Requester::SUPPORTED_METHODS.each do |method|
|
237
|
+
expect { Requester.new(method, url) }.to raise_error(URI::InvalidURIError)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'rejects nil URIs' do
|
242
|
+
Requester::SUPPORTED_METHODS.each do |method|
|
243
|
+
expect { Requester.new(method, nil) }.to raise_error(ArgumentError)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'rejects unsupported methods' do
|
248
|
+
url = 'https://example.org/'
|
249
|
+
%i[put patch post].each do |method|
|
250
|
+
expect { Requester.new(method, url) }.to raise_error(ArgumentError)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
148
254
|
end
|
149
255
|
end
|
150
256
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: berkeley_library-util
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Moles
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-03-
|
11
|
+
date: 2023-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: berkeley_library-logging
|