nypl_platform_api_client 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.
- checksums.yaml +7 -0
- data/lib/errors.rb +5 -0
- data/lib/nypl_platform_api_client.rb +148 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1df8231c019f86e347ab7fa83b1f13db8aa1f02ef3488c1aa5eb055cbaacc63e
|
4
|
+
data.tar.gz: ecd9488ca99d6790e4e35362840861636f5b34a34aaf68a42f4cc963db090ef2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 42b3a9a06976b667c9ac2dd80742d421adc0af0d65c133798bd19ebd602d728e742285e3c2c8e3f13bfce4cc76e1389f4c517a29aacb60384fa4b29362e08aff
|
7
|
+
data.tar.gz: f9c3acf9e5a9e2ff9bc8520049f83a027c5b6271668d60697f09eb4fb66af651ba0be0d481ce9495e59d81bba1196415bc73e18fe3eac2c14d45c33e7e408657
|
data/lib/errors.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
require_relative 'errors'
|
6
|
+
|
7
|
+
class NyplPlatformApiClient
|
8
|
+
def initialize(config = {})
|
9
|
+
@config = {
|
10
|
+
base_url: ENV['PLATFORM_API_BASE_URL'],
|
11
|
+
client_id: ENV['NYPL_OAUTH_ID'],
|
12
|
+
client_secret: ENV['NYPL_OAUTH_SECRET'],
|
13
|
+
oauth_url: ENV['NYPL_OAUTH_URL'],
|
14
|
+
log_level: 'info'
|
15
|
+
}.merge config
|
16
|
+
|
17
|
+
raise NyplPlatformApiClientError.new 'Missing config: neither config.base_url nor ENV.PLATFORM_API_BASE_URL are set' unless @config[:base_url]
|
18
|
+
raise NyplPlatformApiClientError.new 'Missing config: neither config.client_id nor ENV.NYPL_OAUTH_ID are set' unless @config[:client_id]
|
19
|
+
raise NyplPlatformApiClientError.new 'Missing config: neither config.client_secret nor ENV.NYPL_OAUTH_SECRET are set ' unless @config[:client_secret]
|
20
|
+
raise NyplPlatformApiClientError.new 'Missing config: neither config.oauth_url nor ENV.NYPL_OAUTH_URL are set ' unless @config[:oauth_url]
|
21
|
+
end
|
22
|
+
|
23
|
+
def get (path, options = {})
|
24
|
+
options = parse_http_options options
|
25
|
+
|
26
|
+
authenticate! if options[:authenticated]
|
27
|
+
|
28
|
+
uri = URI.parse("#{@config[:base_url]}#{path}")
|
29
|
+
|
30
|
+
logger.debug "NyplPlatformApiClient: Getting from platform api", { uri: uri }
|
31
|
+
|
32
|
+
begin
|
33
|
+
request = Net::HTTP::Get.new(uri)
|
34
|
+
|
35
|
+
# Add bearer token header
|
36
|
+
request["Authorization"] = "Bearer #{@access_token}" if options[:authenticated]
|
37
|
+
|
38
|
+
# Execute request:
|
39
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme === 'https') do |http|
|
40
|
+
http.request(request)
|
41
|
+
end
|
42
|
+
rescue Exception => e
|
43
|
+
raise NyplPlatformApiClientError.new(e), "Failed to GET #{path}: #{e.message}"
|
44
|
+
end
|
45
|
+
|
46
|
+
logger.debug "NyplPlatformApiClient: Got platform api response", { code: response.code, body: response.body }
|
47
|
+
|
48
|
+
parse_json_response response
|
49
|
+
end
|
50
|
+
|
51
|
+
def post (path, body, options = {})
|
52
|
+
options = parse_http_options options
|
53
|
+
|
54
|
+
# Default to POSTing JSON unless explicitly stated otherwise
|
55
|
+
options[:headers]['Content-Type'] = 'application/json' unless options[:headers]['Content-Type']
|
56
|
+
|
57
|
+
authenticate! if options[:authenticated]
|
58
|
+
|
59
|
+
uri = URI.parse("#{@config[:base_url]}#{path}")
|
60
|
+
|
61
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
62
|
+
http.use_ssl = uri.scheme === 'https'
|
63
|
+
|
64
|
+
begin
|
65
|
+
request = Net::HTTP::Post.new(uri.path, 'Content-Type' => options[:headers]['Content-Type'])
|
66
|
+
request.body = body.to_json
|
67
|
+
|
68
|
+
logger.debug "NyplPlatformApiClient: Posting to platform api", { uri: uri, body: body }
|
69
|
+
|
70
|
+
# Add bearer token header
|
71
|
+
request['Authorization'] = "Bearer #{@access_token}" if options[:authenticated]
|
72
|
+
|
73
|
+
# Execute request:
|
74
|
+
response = http.request(request)
|
75
|
+
rescue Exception => e
|
76
|
+
raise NyplPlatformApiClientError.new(e), "Failed to POST to #{path}: #{e.message}"
|
77
|
+
end
|
78
|
+
|
79
|
+
logger.debug "NyplPlatformApiClient: Got platform api response", { code: response.code, body: response.body }
|
80
|
+
|
81
|
+
parse_json_response response
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def parse_http_options (_options)
|
87
|
+
options = {
|
88
|
+
authenticated: true
|
89
|
+
}.merge _options
|
90
|
+
|
91
|
+
options[:headers] = {
|
92
|
+
}.merge(_options[:headers] || {})
|
93
|
+
.transform_keys(&:to_s)
|
94
|
+
|
95
|
+
options
|
96
|
+
end
|
97
|
+
|
98
|
+
def parse_json_response (response)
|
99
|
+
# Among NYPL services, these are the only non-error statuses with useful JSON payloads:
|
100
|
+
if ['200', '404'].include? response.code
|
101
|
+
begin
|
102
|
+
JSON.parse(response.body)
|
103
|
+
rescue => e
|
104
|
+
raise NyplPlatformApiClientError, "Error parsing response (#{response.code}): #{response.body}"
|
105
|
+
end
|
106
|
+
elsif response.code == "401"
|
107
|
+
# Likely an expired access-token; Wipe it for next run
|
108
|
+
@access_token = nil
|
109
|
+
raise NyplPlatformApiClientTokenError.new("Got a 401: #{response.body}")
|
110
|
+
else
|
111
|
+
raise NyplPlatformApiClientError, "Error interpretting response (#{response.code}): #{response.body}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Authorizes the request.
|
116
|
+
def authenticate!
|
117
|
+
# NOOP if we've already authenticated
|
118
|
+
return nil if ! @access_token.nil?
|
119
|
+
|
120
|
+
logger.debug "NyplPlatformApiClient: Authenticating with client_id #{@config[:client_id]}"
|
121
|
+
|
122
|
+
uri = URI.parse("#{@config[:oauth_url]}oauth/token")
|
123
|
+
request = Net::HTTP::Post.new(uri)
|
124
|
+
request.basic_auth(@config[:client_id], @config[:client_secret])
|
125
|
+
request.set_form_data(
|
126
|
+
"grant_type" => "client_credentials"
|
127
|
+
)
|
128
|
+
|
129
|
+
req_options = {
|
130
|
+
use_ssl: uri.scheme == "https",
|
131
|
+
request_timeout: 500
|
132
|
+
}
|
133
|
+
|
134
|
+
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
135
|
+
http.request(request)
|
136
|
+
end
|
137
|
+
|
138
|
+
if response.code == '200'
|
139
|
+
@access_token = JSON.parse(response.body)["access_token"]
|
140
|
+
else
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def logger
|
146
|
+
@logger ||= NyplLogFormatter.new(STDOUT, level: @config[:log_level])
|
147
|
+
end
|
148
|
+
end
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nypl_platform_api_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- nonword
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-10-23 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Client for querying NYPL's internal Platform API
|
14
|
+
email: paulbeaudoin@nypl.org
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/errors.rb
|
20
|
+
- lib/nypl_platform_api_client.rb
|
21
|
+
homepage: https://github.com/NYPL/ruby_nypl_platform_nypl_client
|
22
|
+
licenses:
|
23
|
+
- MIT
|
24
|
+
metadata: {}
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
requirements: []
|
40
|
+
rubyforge_project:
|
41
|
+
rubygems_version: 2.7.3
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: NYPL Platform API client
|
45
|
+
test_files: []
|