nypl_sierra_api_client 1.0.3 → 1.3.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/lib/nypl_sierra_api_client.rb +81 -16
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7216ca46bebde733ae89eca1d88081d1d5cf2db7543dcdf801e433a4400ee4c4
|
4
|
+
data.tar.gz: bc2076e537315b8324bd4f54748090d68aa1d23c761aa9b44d948e95347864e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee64dd2daae74d47757acba0df00a61c0e8b00d6f52a35a3c2c1fc53f43a8542436dac51463cd723c66333f122c70b07abe6db1e2ef7d78899f084206f14d29b
|
7
|
+
data.tar.gz: 7c09588f8be4a03f56519523008b116443930ef0b39880d14860305aa64278cbfec5a0ba1b9216ab1dced91b757013ed820abea4f0c96496488ec216ae023c86
|
@@ -27,6 +27,25 @@ class SierraApiClient
|
|
27
27
|
config_defaults[:env].each do |key, value|
|
28
28
|
raise SierraApiClientError.new "Missing config: neither config.#{key} nor ENV.#{value} are set" unless @config[key]
|
29
29
|
end
|
30
|
+
|
31
|
+
@retries = 0
|
32
|
+
end
|
33
|
+
|
34
|
+
def put (path, body, options = {})
|
35
|
+
options = parse_http_options options
|
36
|
+
# Default to POSTing JSON unless explicitly stated otherwise
|
37
|
+
options[:headers]['Content-Type'] = 'application/json' unless options[:headers]['Content-Type']
|
38
|
+
|
39
|
+
do_request 'put', path, options do |request|
|
40
|
+
request.body = body
|
41
|
+
request.body = request.body.to_json unless options[:headers]['Content-Type'] != 'application/json'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete (path, options = {})
|
46
|
+
options = parse_http_options options
|
47
|
+
|
48
|
+
do_request 'delete', path, options
|
30
49
|
end
|
31
50
|
|
32
51
|
def get (path, options = {})
|
@@ -50,22 +69,19 @@ class SierraApiClient
|
|
50
69
|
private
|
51
70
|
|
52
71
|
def do_request (method, path, options = {})
|
53
|
-
# For now, these are the methods we support:
|
54
|
-
raise SierraApiClientError, "Unsupported method: #{method}" unless ['get', 'post'].include? method.downcase
|
55
72
|
|
56
|
-
|
73
|
+
raise SierraApiClientError, "Unsupported method: #{method}" unless ['get', 'post', 'put', 'delete'].include? method.downcase
|
57
74
|
|
58
|
-
|
75
|
+
authenticate! if options[:authenticated]
|
59
76
|
|
60
|
-
|
61
|
-
http.use_ssl = uri.scheme === 'https'
|
77
|
+
@uri = URI.parse("#{@config[:base_url]}#{path}")
|
62
78
|
|
63
79
|
# Build request headers:
|
64
80
|
request_headers = {}
|
65
81
|
request_headers['Content-Type'] = options[:headers]['Content-Type'] unless options.dig(:headers, 'Content-Type').nil?
|
66
82
|
|
67
83
|
# Create HTTP::Get or HTTP::Post
|
68
|
-
request = Net::HTTP.const_get(method.capitalize).new(uri, request_headers)
|
84
|
+
request = Net::HTTP.const_get(method.capitalize).new(@uri, request_headers)
|
69
85
|
|
70
86
|
# Add bearer token header
|
71
87
|
request['Authorization'] = "Bearer #{@access_token}" if options[:authenticated]
|
@@ -73,31 +89,76 @@ class SierraApiClient
|
|
73
89
|
# Allow caller to modify the request before we send it off:
|
74
90
|
yield request if block_given?
|
75
91
|
|
76
|
-
logger.debug "SierraApiClient: #{method} to Sierra api", { uri: uri, body: request.body }
|
92
|
+
logger.debug "SierraApiClient: #{method} to Sierra api", { uri: @uri, body: request.body }
|
93
|
+
|
94
|
+
execute request, options
|
95
|
+
end
|
96
|
+
|
97
|
+
def execute (request, options)
|
98
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
99
|
+
http.use_ssl = @uri.scheme === 'https'
|
77
100
|
|
78
101
|
begin
|
79
|
-
# Execute request:
|
80
102
|
response = http.request(request)
|
103
|
+
logger.debug "SierraApiClient: Got Sierra api response", { code: response.code, body: response.body }
|
81
104
|
rescue => e
|
82
|
-
raise SierraApiClientError.new
|
105
|
+
raise SierraApiClientError.new "Failed to #{request.method} to #{request.path}: #{e.message}"
|
83
106
|
end
|
84
107
|
|
85
|
-
|
86
|
-
|
87
|
-
parse_response response
|
108
|
+
handle_response response, request, options
|
88
109
|
end
|
89
110
|
|
90
|
-
def
|
111
|
+
def handle_response (response, request, options)
|
91
112
|
if response.code == "401"
|
92
113
|
# Likely an expired access-token; Wipe it for next run
|
93
|
-
# TODO: Implement token refresh
|
94
114
|
@access_token = nil
|
95
|
-
|
115
|
+
if @retries < 3
|
116
|
+
if options[:authenticated]
|
117
|
+
logger.debug "SierraApiClient: Refreshing oauth token for 401", { code: 401, body: response.body, retry: @retries }
|
118
|
+
|
119
|
+
return reauthenticate_and_reattempt request, options
|
120
|
+
end
|
121
|
+
else
|
122
|
+
retries_exceeded = true
|
123
|
+
end
|
124
|
+
|
125
|
+
reset_retries
|
126
|
+
message = "Got a 401: #{retries_exceeded ? "Maximum retries exceeded, " : ''}#{response.body}"
|
127
|
+
raise SierraApiClientTokenError.new(message)
|
96
128
|
end
|
97
129
|
|
130
|
+
if response.body == '' && response.code.to_i < 300 && response.code.to_i >= 200
|
131
|
+
reattempt_request request, options
|
132
|
+
end
|
133
|
+
|
134
|
+
reset_retries if @retries > 0
|
98
135
|
SierraApiResponse.new(response)
|
99
136
|
end
|
100
137
|
|
138
|
+
|
139
|
+
def reattempt_request request, options
|
140
|
+
if @retries < 3
|
141
|
+
logger.warn "#{request.method} request retry ##{@retries} due to empty response from Sierra API"
|
142
|
+
sleep 2 ** (@retries - 1)
|
143
|
+
@retries += 1
|
144
|
+
execute request, options
|
145
|
+
else
|
146
|
+
reset_retries
|
147
|
+
raise SierraApiResponseError.new "Sierra API Client: Request failed after 3 empty responses received from Sierra API"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
def reauthenticate_and_reattempt request, options
|
153
|
+
@retries += 1
|
154
|
+
sleep 2 ** (@retries - 1)
|
155
|
+
authenticate!
|
156
|
+
# Reset bearer token header
|
157
|
+
request['Authorization'] = "Bearer #{@access_token}"
|
158
|
+
|
159
|
+
execute request, options
|
160
|
+
end
|
161
|
+
|
101
162
|
def parse_http_options (_options)
|
102
163
|
options = {
|
103
164
|
authenticated: true
|
@@ -143,4 +204,8 @@ class SierraApiClient
|
|
143
204
|
def logger
|
144
205
|
@logger ||= NyplLogFormatter.new(STDOUT, level: @config[:log_level])
|
145
206
|
end
|
207
|
+
|
208
|
+
def reset_retries
|
209
|
+
@retries = 0
|
210
|
+
end
|
146
211
|
end
|