etrieve_content_api 0.1.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/.gitignore +8 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +52 -0
- data/LICENSE.txt +29 -0
- data/README.md +75 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/etrieve_api.gemspec +35 -0
- data/lib/etrieve_content_api.rb +16 -0
- data/lib/etrieve_content_api/authentication_error.rb +4 -0
- data/lib/etrieve_content_api/connection.rb +208 -0
- data/lib/etrieve_content_api/connection_configuration_error.rb +4 -0
- data/lib/etrieve_content_api/handler.rb +135 -0
- data/lib/etrieve_content_api/version.rb +5 -0
- metadata +142 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: af777b64e204b218402cc4f526681ede5729f849383d5bb086196360fde177b9
|
|
4
|
+
data.tar.gz: 887ca59fa507311bc3badb82da2d3c900840429a386830f3c5c777c06db978ef
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6f57140e04e36ab762ce243397471f914f25339b0e2b7c71a08cd811f63b066e9efd7c9efd8a447ddae9ff9502e0344f37a2f9ce8b3b66b550e450a8fd8bd8ff
|
|
7
|
+
data.tar.gz: fc2e24aee98822d0916af2107317cd5a1355628adbc4eaf0c996e2d477a1d919ad5ee0aec50c07bcaf8af5a5a21856a19c541f1637afed15a5e988431f3465e8
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
etrieve_content_api (0.1.0)
|
|
5
|
+
json
|
|
6
|
+
rest-client
|
|
7
|
+
|
|
8
|
+
GEM
|
|
9
|
+
remote: https://rubygems.org/
|
|
10
|
+
specs:
|
|
11
|
+
addressable (2.6.0)
|
|
12
|
+
public_suffix (>= 2.0.2, < 4.0)
|
|
13
|
+
crack (0.4.3)
|
|
14
|
+
safe_yaml (~> 1.0.0)
|
|
15
|
+
domain_name (0.5.20180417)
|
|
16
|
+
unf (>= 0.0.5, < 1.0.0)
|
|
17
|
+
hashdiff (0.4.0)
|
|
18
|
+
http-cookie (1.0.3)
|
|
19
|
+
domain_name (~> 0.5)
|
|
20
|
+
json (2.2.0)
|
|
21
|
+
mime-types (3.2.2)
|
|
22
|
+
mime-types-data (~> 3.2015)
|
|
23
|
+
mime-types-data (3.2019.0331)
|
|
24
|
+
minitest (5.11.3)
|
|
25
|
+
netrc (0.11.0)
|
|
26
|
+
public_suffix (3.1.0)
|
|
27
|
+
rake (10.5.0)
|
|
28
|
+
rest-client (2.0.2)
|
|
29
|
+
http-cookie (>= 1.0.2, < 2.0)
|
|
30
|
+
mime-types (>= 1.16, < 4.0)
|
|
31
|
+
netrc (~> 0.8)
|
|
32
|
+
safe_yaml (1.0.5)
|
|
33
|
+
unf (0.1.4)
|
|
34
|
+
unf_ext
|
|
35
|
+
unf_ext (0.0.7.6)
|
|
36
|
+
webmock (3.6.0)
|
|
37
|
+
addressable (>= 2.3.6)
|
|
38
|
+
crack (>= 0.3.2)
|
|
39
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
40
|
+
|
|
41
|
+
PLATFORMS
|
|
42
|
+
ruby
|
|
43
|
+
|
|
44
|
+
DEPENDENCIES
|
|
45
|
+
bundler (~> 1.16)
|
|
46
|
+
etrieve_content_api!
|
|
47
|
+
minitest
|
|
48
|
+
rake (~> 10.0)
|
|
49
|
+
webmock
|
|
50
|
+
|
|
51
|
+
BUNDLED WITH
|
|
52
|
+
1.16.4
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019, Reed College
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# EtrieveContentApi
|
|
2
|
+
|
|
3
|
+
Ruby wrapper for accessing the Etrieve Content API. Document metadata and content retrieval is currently supported. Document writes may be supported in a future version.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'etrieve_content_api'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
$ bundle
|
|
16
|
+
|
|
17
|
+
Or install it yourself as:
|
|
18
|
+
|
|
19
|
+
$ gem install etrieve_content_api
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Configuration
|
|
23
|
+
|
|
24
|
+
Configuration can be passed as a hash.
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
{
|
|
28
|
+
auth_url: 'https://example.com/auth', # default: ''
|
|
29
|
+
base_url: 'https://example.com/api', # default: ''
|
|
30
|
+
password: password, # default: ''
|
|
31
|
+
username: username, # default: ''
|
|
32
|
+
timeout: 1, # default: 30 seconds
|
|
33
|
+
verify_ssl: false # default: true
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Configuration can be read from a YAML file by passing the file path. The file should contain a hash structure and ERB content is evaluated:
|
|
38
|
+
```yaml
|
|
39
|
+
---
|
|
40
|
+
auth_url: 'https://example.com/auth',
|
|
41
|
+
base_url: 'https://example.com/api',
|
|
42
|
+
password: password,
|
|
43
|
+
username: username,
|
|
44
|
+
timeout: 1,
|
|
45
|
+
verify_ssl: false
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
### Basic Request
|
|
50
|
+
|
|
51
|
+
See [Handler](lib/etrieve_content_api/handler.rb) class for prebuilt requests for things like document metadata and content.
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
require 'etrieve_content_api'
|
|
55
|
+
handler = EtrieveContentApi::Handler.new(config_hash_or_path_to_config_yaml)
|
|
56
|
+
handler.document_metadata({:q => 'Sue'})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Using EtrieveContentApi::Connection
|
|
60
|
+
Connection#execute can be used to wrap a group of calls with a single authentication request.
|
|
61
|
+
```ruby
|
|
62
|
+
conn = EtrieveContentApi::Connection.new(config_hash_or_path_to_config_yaml)
|
|
63
|
+
conn.execute() {
|
|
64
|
+
@custom1 = conn.get_custom_connection([conn.base_url, 'custom_path1'].join('/'), conn.headers)
|
|
65
|
+
@custom2 = conn.get_custom_connection([conn.base_url, 'custom_path2'].join('/'), conn.headers)
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Contributing
|
|
70
|
+
|
|
71
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/reed_college/etrieve_content_api.
|
|
72
|
+
|
|
73
|
+
## License
|
|
74
|
+
|
|
75
|
+
The gem is available as open source under the terms of the [ BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause).
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "etrieve_content_api"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/etrieve_api.gemspec
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
lib = File.expand_path('lib', __dir__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'etrieve_content_api/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'etrieve_content_api'
|
|
8
|
+
spec.version = EtrieveContentApi::Version::VERSION
|
|
9
|
+
spec.authors = ['Shannon Henderson']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'A Ruby wrapper for the Etrieve Content API'
|
|
12
|
+
spec.description = "Interact with Etrieve Content's REST API"
|
|
13
|
+
spec.homepage = 'https://github.com/reed-college/etrieve_content_api'
|
|
14
|
+
spec.license = 'BSD-3-Clause'
|
|
15
|
+
|
|
16
|
+
# Specify which files should be added to the gem when it is released.
|
|
17
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
18
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
19
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
20
|
+
end
|
|
21
|
+
spec.bindir = 'exe'
|
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
24
|
+
spec.require_paths = ['lib']
|
|
25
|
+
|
|
26
|
+
spec.add_runtime_dependency 'json'
|
|
27
|
+
spec.add_runtime_dependency 'rest-client'
|
|
28
|
+
|
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
|
30
|
+
spec.add_development_dependency 'minitest'
|
|
31
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
32
|
+
spec.add_development_dependency 'webmock'
|
|
33
|
+
|
|
34
|
+
spec.required_ruby_version = '>= 2.1.0'
|
|
35
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
require 'erb'
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'rest_client'
|
|
5
|
+
require 'uri'
|
|
6
|
+
require 'yaml'
|
|
7
|
+
|
|
8
|
+
require 'etrieve_content_api/version'
|
|
9
|
+
require 'etrieve_content_api/connection'
|
|
10
|
+
require 'etrieve_content_api/handler'
|
|
11
|
+
require 'etrieve_content_api/authentication_error'
|
|
12
|
+
require 'etrieve_content_api/connection_configuration_error'
|
|
13
|
+
|
|
14
|
+
module EtrieveContentApi
|
|
15
|
+
# Your code goes here...
|
|
16
|
+
end
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
module EtrieveContentApi
|
|
2
|
+
# Auth wrapper for and actual rest client calls to Etrieve Content API
|
|
3
|
+
class Connection
|
|
4
|
+
attr_reader :auth_url
|
|
5
|
+
attr_reader :base_url
|
|
6
|
+
attr_reader :connection
|
|
7
|
+
attr_reader :headers
|
|
8
|
+
attr_reader :timeout
|
|
9
|
+
attr_reader :expires_at
|
|
10
|
+
attr_reader :username
|
|
11
|
+
attr_reader :verify_ssl
|
|
12
|
+
|
|
13
|
+
CONFIG_KEYS = %i[
|
|
14
|
+
auth_url
|
|
15
|
+
base_url
|
|
16
|
+
password
|
|
17
|
+
timeout
|
|
18
|
+
username
|
|
19
|
+
verify_ssl
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
def initialize(config)
|
|
23
|
+
if config.is_a?(String)
|
|
24
|
+
configure_with(config)
|
|
25
|
+
elsif config.is_a?(Hash)
|
|
26
|
+
configure(config)
|
|
27
|
+
else
|
|
28
|
+
raise ConnectionConfigurationError,
|
|
29
|
+
'Invalid configuration options supplied.'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.auth_token(user, password)
|
|
34
|
+
Base64.strict_encode64 [user, password].join(':')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def auth_token
|
|
38
|
+
@auth_token ||= self.class.auth_token(username, @password)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def connect
|
|
42
|
+
return @connection if @connection && active?
|
|
43
|
+
begin
|
|
44
|
+
resp = post_custom_connection(
|
|
45
|
+
auth_url,
|
|
46
|
+
payload: 'grant_type=client_credentials&scope=openid',
|
|
47
|
+
headers: {
|
|
48
|
+
authorization: "Basic #{auth_token}",
|
|
49
|
+
accept: :json
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
results = JSON.parse(resp)
|
|
53
|
+
rescue RestClient::ExceptionWithResponse => err
|
|
54
|
+
results = JSON.parse(err.response)
|
|
55
|
+
rescue
|
|
56
|
+
results = { error: $!.message }
|
|
57
|
+
end
|
|
58
|
+
@access_token = results['access_token']
|
|
59
|
+
if @access_token
|
|
60
|
+
@headers = { authorization: "Bearer #{@access_token}" }
|
|
61
|
+
@connection = results
|
|
62
|
+
@expires_at = Time.now + results['expires_in'].to_i
|
|
63
|
+
else
|
|
64
|
+
reset!
|
|
65
|
+
end
|
|
66
|
+
results
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def connect!
|
|
70
|
+
reset!
|
|
71
|
+
connect
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def active?
|
|
75
|
+
return false unless @expires_at.is_a?(Time)
|
|
76
|
+
return false if @expires_at < Time.now - 5
|
|
77
|
+
true
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def reset!
|
|
81
|
+
configure(@config)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def get(path, headers: {}, &block)
|
|
85
|
+
execute(headers: headers) do
|
|
86
|
+
get_custom_connection path, headers: @headers, &block
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def post(path, payload: nil, headers: {}, &block)
|
|
91
|
+
execute(headers: headers) do
|
|
92
|
+
post_custom_connection path, payload: payload, headers: @headers, &block
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# TODO: pass headers differently
|
|
97
|
+
def execute(headers: {}, &block)
|
|
98
|
+
connect
|
|
99
|
+
return false unless @connection
|
|
100
|
+
hold_headers = @headers
|
|
101
|
+
@headers = merge_headers(headers)
|
|
102
|
+
out = yield(block)
|
|
103
|
+
@headers = hold_headers
|
|
104
|
+
out
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Use this inside an execute block to make mulitiple calls in the same
|
|
108
|
+
# request
|
|
109
|
+
def get_custom_connection(path = '', headers: {}, &block)
|
|
110
|
+
block ||= default_response_handler
|
|
111
|
+
url = path =~ /\Ahttp/ ? path : [@base_url, path].join('/')
|
|
112
|
+
rest_client_wrapper :get, url, headers: headers, &block
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Use this inside an execute block to make mulitiple calls in the same
|
|
116
|
+
# request
|
|
117
|
+
def post_custom_connection(path, payload: nil, headers: {}, &block)
|
|
118
|
+
path ||= ''
|
|
119
|
+
block ||= default_response_handler
|
|
120
|
+
url = path =~ /\Ahttp/ ? path : [@base_url, path].join('/')
|
|
121
|
+
RestClient::Request.execute(
|
|
122
|
+
method: :post,
|
|
123
|
+
url: url,
|
|
124
|
+
payload: payload,
|
|
125
|
+
headers: headers,
|
|
126
|
+
verify_ssl: verify_ssl,
|
|
127
|
+
timeout: timeout,
|
|
128
|
+
&block
|
|
129
|
+
)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
private
|
|
133
|
+
|
|
134
|
+
def rest_client_wrapper(method, url, headers: {}, &block)
|
|
135
|
+
RestClient::Request.execute(
|
|
136
|
+
method: method,
|
|
137
|
+
url: url,
|
|
138
|
+
headers: headers,
|
|
139
|
+
verify_ssl: verify_ssl,
|
|
140
|
+
timeout: timeout,
|
|
141
|
+
&block
|
|
142
|
+
)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Configure using hash
|
|
146
|
+
def configure(opts = {})
|
|
147
|
+
@config = clean_config_hash(opts)
|
|
148
|
+
|
|
149
|
+
@access_token = nil
|
|
150
|
+
@auth_url = @config[:auth_url] || ''
|
|
151
|
+
@base_url = @config[:base_url] || ''
|
|
152
|
+
@connection = nil
|
|
153
|
+
@headers = {}
|
|
154
|
+
@request_headers = {}
|
|
155
|
+
@password = @config[:password] || ''
|
|
156
|
+
@timeout = @config[:timeout] || 30
|
|
157
|
+
@username = @config[:username] || ''
|
|
158
|
+
@verify_ssl = @config[:verify_ssl] != false
|
|
159
|
+
@expires_at = nil
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Configure with yaml
|
|
163
|
+
def configure_with(path_to_yaml_file)
|
|
164
|
+
unless path_to_yaml_file.is_a?(String)
|
|
165
|
+
raise ConnectionConfigurationError,
|
|
166
|
+
'Invalid request. #configure_with requires string'
|
|
167
|
+
end
|
|
168
|
+
begin
|
|
169
|
+
config = YAML.safe_load(
|
|
170
|
+
ERB.new(IO.read(path_to_yaml_file)).result,
|
|
171
|
+
symbolize_names: true
|
|
172
|
+
)
|
|
173
|
+
rescue Errno::ENOENT
|
|
174
|
+
raise ConnectionConfigurationError,
|
|
175
|
+
'YAML configuration file was not found.'
|
|
176
|
+
rescue Psych::SyntaxError
|
|
177
|
+
raise ConnectionConfigurationError,
|
|
178
|
+
'YAML configuration file contains invalid syntax.'
|
|
179
|
+
end
|
|
180
|
+
configure(config)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def clean_config_hash(config)
|
|
184
|
+
config = config.inject({}) { |h, (k, v)| h[k.to_sym] = v; h }
|
|
185
|
+
CONFIG_KEYS.inject({}) { |h, k| h[k] = config[k]; h }
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def merge_headers(headers = {})
|
|
189
|
+
headers = @headers.merge(headers)
|
|
190
|
+
headers[:auth_token] = @auth_token
|
|
191
|
+
headers
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def default_response_handler
|
|
195
|
+
@default_response_handler ||= lambda do |response, _request, _result, &block|
|
|
196
|
+
case response.code
|
|
197
|
+
when 200
|
|
198
|
+
return response
|
|
199
|
+
when 401
|
|
200
|
+
raise AuthenticationError, response.body
|
|
201
|
+
else
|
|
202
|
+
# Some other error. Let it bubble up.
|
|
203
|
+
response.return!(&block)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
module EtrieveContentApi
|
|
2
|
+
class Handler
|
|
3
|
+
API_PATH = 'api'.freeze
|
|
4
|
+
DOCUMENTS_PATH = [API_PATH, 'documents'].join('/').freeze
|
|
5
|
+
|
|
6
|
+
DOCUMENT_METADATA_PARAMS = %i[
|
|
7
|
+
area_code
|
|
8
|
+
document_type_code
|
|
9
|
+
field_code
|
|
10
|
+
field_value
|
|
11
|
+
fields
|
|
12
|
+
limit
|
|
13
|
+
offset
|
|
14
|
+
q
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
PAGE_CONTENT_PARAMS = %i[dpi height width include_annotations].freeze
|
|
18
|
+
|
|
19
|
+
DOCUMENT_CONTENT_PARAMS = %i[include_annotations].freeze
|
|
20
|
+
|
|
21
|
+
attr_reader :connection
|
|
22
|
+
|
|
23
|
+
def initialize(connection_config)
|
|
24
|
+
@config = connection_config
|
|
25
|
+
@connection = Connection.new(@config)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Get information for one or more documents
|
|
29
|
+
# query:
|
|
30
|
+
# q: simple search
|
|
31
|
+
# area_code: document area
|
|
32
|
+
# document_type_code: document type
|
|
33
|
+
# field_code: field name for exact match of value in field_value
|
|
34
|
+
# field_value: field value for field_code
|
|
35
|
+
# limit: number of items to return
|
|
36
|
+
# offset: number of items to skip
|
|
37
|
+
# fields: comma-delimited list of fields to include
|
|
38
|
+
def document_metadata(query: {}, headers: {}, &block)
|
|
39
|
+
query_s = encoded_query(
|
|
40
|
+
query: query,
|
|
41
|
+
keys_allowed: DOCUMENT_METADATA_PARAMS
|
|
42
|
+
)
|
|
43
|
+
get_json DOCUMENTS_PATH, query: query_s, headers: headers, &block
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Calls #document_metadata in a loop retrieving per_request number of
|
|
47
|
+
# documents until all matching docs are retrieved or loop_max is reached
|
|
48
|
+
def all_document_metadata(
|
|
49
|
+
query: {}, headers: {}, per_request: 25, loop_max: 10, &block
|
|
50
|
+
)
|
|
51
|
+
query[:limit] = per_request
|
|
52
|
+
out = []
|
|
53
|
+
loop_max.times do
|
|
54
|
+
docs, resp_headers = document_metadata(query: query, headers: headers, &block)
|
|
55
|
+
docs.empty? ? break : out << docs
|
|
56
|
+
break if resp_headers[:x_hasmore] == 'False'
|
|
57
|
+
query[:offset] = (query[:offset] || 0) + per_request
|
|
58
|
+
end
|
|
59
|
+
out.flatten
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Get content of a document
|
|
63
|
+
# query:
|
|
64
|
+
# include_annotations: include all annotations? true/false
|
|
65
|
+
def document_content(document_id, query: {}, headers: {}, &block)
|
|
66
|
+
path = [DOCUMENTS_PATH, document_id, 'contents'].join('/')
|
|
67
|
+
query_s = encoded_query(
|
|
68
|
+
query: query,
|
|
69
|
+
keys_allowed: DOCUMENT_CONTENT_PARAMS
|
|
70
|
+
)
|
|
71
|
+
get path, query: query_s, headers: headers, &block
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Get an image of a specific page of a document
|
|
75
|
+
# query:
|
|
76
|
+
# height: max height
|
|
77
|
+
# width: max width
|
|
78
|
+
# dpi: dots per inch
|
|
79
|
+
# include_annotations: include all annotations? true/false
|
|
80
|
+
def page_content(document_id, page: 1, query: {}, headers: {}, &block)
|
|
81
|
+
path = [DOCUMENTS_PATH, document_id, 'contents', page].join('/')
|
|
82
|
+
query_s = encoded_query(
|
|
83
|
+
query: query,
|
|
84
|
+
keys_allowed: PAGE_CONTENT_PARAMS
|
|
85
|
+
)
|
|
86
|
+
get path, query: query_s, headers: headers, &block
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Format a request and pass it on to the connection's get method
|
|
90
|
+
def get(path = '', query: '', headers: {}, &block)
|
|
91
|
+
query = query.empty? ? nil : query
|
|
92
|
+
path = [path, query].compact.join('?')
|
|
93
|
+
connection.get path, headers: headers, &block
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Process content from #get and parse JSON from body.
|
|
97
|
+
def get_json(path = '', query: '', headers: {}, &block)
|
|
98
|
+
r = get path, query: query, headers: headers, &block
|
|
99
|
+
return { message: r } unless r.respond_to?(:body)
|
|
100
|
+
|
|
101
|
+
json = begin
|
|
102
|
+
JSON.parse(r.body)
|
|
103
|
+
rescue JSON::ParserError
|
|
104
|
+
{}
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
[json, r.headers]
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
def encoded_query(query: {}, keys_allowed: :all)
|
|
113
|
+
filtered_params = slice_hash(
|
|
114
|
+
query, keys_allowed
|
|
115
|
+
).select do |_k, v|
|
|
116
|
+
!v.nil? && !v.to_s.empty?
|
|
117
|
+
end
|
|
118
|
+
renamed_params = filtered_params.inject({}) do |h, (k, v)|
|
|
119
|
+
h[camelize(k)] = v
|
|
120
|
+
h
|
|
121
|
+
end
|
|
122
|
+
URI.encode_www_form(renamed_params)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Keep only specified keys
|
|
126
|
+
def slice_hash(orig_hash, keys_allowed = :all)
|
|
127
|
+
return orig_hash if keys_allowed == :all
|
|
128
|
+
orig_hash.select { |k, _v| keys_allowed.include?(k) }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def camelize(str)
|
|
132
|
+
str.to_s.split('_').map(&:capitalize).join.sub(/^[A-Z]/, &:downcase)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: etrieve_content_api
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Shannon Henderson
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2019-08-27 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: json
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rest-client
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: bundler
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.16'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.16'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: minitest
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rake
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '10.0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '10.0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: webmock
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
description: Interact with Etrieve Content's REST API
|
|
98
|
+
email:
|
|
99
|
+
executables: []
|
|
100
|
+
extensions: []
|
|
101
|
+
extra_rdoc_files: []
|
|
102
|
+
files:
|
|
103
|
+
- ".gitignore"
|
|
104
|
+
- Gemfile
|
|
105
|
+
- Gemfile.lock
|
|
106
|
+
- LICENSE.txt
|
|
107
|
+
- README.md
|
|
108
|
+
- Rakefile
|
|
109
|
+
- bin/console
|
|
110
|
+
- bin/setup
|
|
111
|
+
- etrieve_api.gemspec
|
|
112
|
+
- lib/etrieve_content_api.rb
|
|
113
|
+
- lib/etrieve_content_api/authentication_error.rb
|
|
114
|
+
- lib/etrieve_content_api/connection.rb
|
|
115
|
+
- lib/etrieve_content_api/connection_configuration_error.rb
|
|
116
|
+
- lib/etrieve_content_api/handler.rb
|
|
117
|
+
- lib/etrieve_content_api/version.rb
|
|
118
|
+
homepage: https://github.com/reed-college/etrieve_content_api
|
|
119
|
+
licenses:
|
|
120
|
+
- BSD-3-Clause
|
|
121
|
+
metadata: {}
|
|
122
|
+
post_install_message:
|
|
123
|
+
rdoc_options: []
|
|
124
|
+
require_paths:
|
|
125
|
+
- lib
|
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: 2.1.0
|
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
|
+
requirements:
|
|
133
|
+
- - ">="
|
|
134
|
+
- !ruby/object:Gem::Version
|
|
135
|
+
version: '0'
|
|
136
|
+
requirements: []
|
|
137
|
+
rubyforge_project:
|
|
138
|
+
rubygems_version: 2.7.6
|
|
139
|
+
signing_key:
|
|
140
|
+
specification_version: 4
|
|
141
|
+
summary: A Ruby wrapper for the Etrieve Content API
|
|
142
|
+
test_files: []
|