nypl_sierra_api_client 1.0.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nypl_sierra_api_client.rb +81 -16
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 227304609f16f96cf643ec758501e7ba23952da2c77cc513d6b08781622da9a8
4
- data.tar.gz: a723fc2eb6e3fc3e33937c513eaddaa05d7a194b9f11fc8eb12f9d2cfd7da594
3
+ metadata.gz: 7216ca46bebde733ae89eca1d88081d1d5cf2db7543dcdf801e433a4400ee4c4
4
+ data.tar.gz: bc2076e537315b8324bd4f54748090d68aa1d23c761aa9b44d948e95347864e8
5
5
  SHA512:
6
- metadata.gz: 213eed76eb255b12e38b00d7460dfb91bc8fac2afa2c92e025fb62019bee8a35d3c664b4713988865ed6b57327b736f3301858a40ae3a8019fad24e50342eb0e
7
- data.tar.gz: 97b00de6b5114deb32da9e72b3490e03e26077c9e23db72f015adc584c5a56a6b912798156fd59021c3d9a43840755b96c4e2b92a113c0a6216cde9edbb53cd5
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
- authenticate! if options[:authenticated]
73
+ raise SierraApiClientError, "Unsupported method: #{method}" unless ['get', 'post', 'put', 'delete'].include? method.downcase
57
74
 
58
- uri = URI.parse("#{@config[:base_url]}#{path}")
75
+ authenticate! if options[:authenticated]
59
76
 
60
- http = Net::HTTP.new(uri.host, uri.port)
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(e), "Failed to #{method} to #{path}: #{e.message}"
105
+ raise SierraApiClientError.new "Failed to #{request.method} to #{request.path}: #{e.message}"
83
106
  end
84
107
 
85
- logger.debug "SierraApiClient: Got Sierra api response", { code: response.code, body: response.body }
86
-
87
- parse_response response
108
+ handle_response response, request, options
88
109
  end
89
110
 
90
- def parse_response (response)
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
- raise SierraApiClientTokenError.new("Got a 401: #{response.body}")
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nypl_sierra_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nonword