stash-sword 0.1.3 → 0.1.4
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/.ruby-version +1 -1
- data/CHANGES.md +5 -0
- data/examples/create.rb +1 -1
- data/lib/stash/sword/client.rb +4 -11
- data/lib/stash/sword/http_helper.rb +15 -7
- data/lib/stash/sword/log_utils.rb +37 -14
- data/lib/stash/sword/module_info.rb +1 -1
- data/spec/unit/stash/sword2/client_spec.rb +22 -3
- data/spec/unit/stash/sword2/log_spec.rb +80 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b73e085f5409cc5c2b3a74c703aacb670bffdc46
|
4
|
+
data.tar.gz: d393a54966e95e40d97d6019022781547fecdad2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49f4a2eddae1eac20a7b8ee10c707287ca10f2e7390bab19fb7ac17a9e809a049a5f680112aa5059c76f2af6d38336ac297783d42786bb03b35230433e7f9787
|
7
|
+
data.tar.gz: 397fcf71c55dad279545b735274293c108989c0e604baa8ad488679cdc88b5beca0a97dfe15fdbfaf85cbd4f8e64167a44d7bacd954ac7dafd4b5af1fcca6664
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.2.
|
1
|
+
2.2.5
|
data/CHANGES.md
CHANGED
data/examples/create.rb
CHANGED
@@ -7,7 +7,7 @@ include Stash::Sword
|
|
7
7
|
password = ARGV[0]
|
8
8
|
username = 'ucop_dash_submitter'
|
9
9
|
collection = 'dash_cdl'
|
10
|
-
collection_uri = "http://
|
10
|
+
collection_uri = "http://sword-aws-dev.cdlib.org:39001/mrtsword/collection/#{collection}"
|
11
11
|
zipfile = File.expand_path('../uploads/example.zip', __FILE__)
|
12
12
|
|
13
13
|
doi = "doi:10.5072/FK#{Time.now.to_i}"
|
data/lib/stash/sword/client.rb
CHANGED
@@ -59,8 +59,8 @@ module Stash
|
|
59
59
|
def update(edit_iri:, zipfile:)
|
60
60
|
log.debug("Stash::Sword::Client.update(edit_iri: #{edit_iri}, zipfile: #{zipfile})")
|
61
61
|
uri = to_uri(edit_iri).to_s
|
62
|
-
response =
|
63
|
-
log.debug(
|
62
|
+
response = do_put(uri, zipfile)
|
63
|
+
log.debug(to_log_msg(response))
|
64
64
|
response.code # TODO: what if anything should we return here?
|
65
65
|
rescue => e
|
66
66
|
log_error(e)
|
@@ -75,15 +75,8 @@ module Stash
|
|
75
75
|
raise 'no password provided' unless password
|
76
76
|
end
|
77
77
|
|
78
|
-
def maybe_redirect(response)
|
79
|
-
return response unless [301, 302, 307].include?(response.code)
|
80
|
-
log.debug(response_to_log_msg(response))
|
81
|
-
log.debug("Response code #{response.code}; redirecting")
|
82
|
-
response.follow_get_redirection
|
83
|
-
end
|
84
|
-
|
85
78
|
def receipt_from(response)
|
86
|
-
log.debug(
|
79
|
+
log.debug(to_log_msg(response))
|
87
80
|
|
88
81
|
body = response.body.strip
|
89
82
|
return DepositReceipt.parse_xml(body) unless body.empty?
|
@@ -97,7 +90,7 @@ module Stash
|
|
97
90
|
return nil unless edit_iri
|
98
91
|
|
99
92
|
log.debug("Retrieving deposit receipt from Location header Edit-IRI: #{edit_iri}")
|
100
|
-
body = helper.get(to_uri(edit_iri))
|
93
|
+
body = helper.get(uri: to_uri(edit_iri))
|
101
94
|
return nil unless body
|
102
95
|
|
103
96
|
DepositReceipt.parse_xml(body)
|
@@ -13,12 +13,18 @@ module Stash
|
|
13
13
|
# The default number of redirects to follow before erroring out.
|
14
14
|
DEFAULT_MAX_REDIRECTS = 5
|
15
15
|
|
16
|
+
# The default number of seconds to allow before timing out. Defaults to 10 minutes.
|
17
|
+
DEFAULT_TIMEOUT = 60 * 10
|
18
|
+
|
16
19
|
# @return [String] the User-Agent string to send when making requests
|
17
20
|
attr_accessor :user_agent
|
18
21
|
|
19
22
|
# @return [Integer] the number of redirects to follow before erroring out
|
20
23
|
attr_accessor :redirect_limit
|
21
24
|
|
25
|
+
# @return [Integer] the number of seconds to allow before timing out
|
26
|
+
attr_accessor :timeout
|
27
|
+
|
22
28
|
# @return [String] the HTTP Basic Authentication username
|
23
29
|
attr_reader :username
|
24
30
|
|
@@ -31,9 +37,10 @@ module Stash
|
|
31
37
|
# @param redirect_limit [Integer] the number of redirects to follow before erroring out
|
32
38
|
# (defaults to {DEFAULT_MAX_REDIRECTS})
|
33
39
|
# @param logger [Logger, nil] the logger to use, or nil to use a default logger
|
34
|
-
def initialize(user_agent:, username: nil, password: nil, redirect_limit: DEFAULT_MAX_REDIRECTS, logger: nil)
|
40
|
+
def initialize(user_agent:, username: nil, password: nil, redirect_limit: DEFAULT_MAX_REDIRECTS, timeout: DEFAULT_TIMEOUT, logger: nil)
|
35
41
|
@user_agent = user_agent
|
36
42
|
@redirect_limit = redirect_limit
|
43
|
+
@timeout = timeout
|
37
44
|
@username = username
|
38
45
|
@password = password
|
39
46
|
@log = logger || default_logger
|
@@ -53,12 +60,12 @@ module Stash
|
|
53
60
|
|
54
61
|
# Posts the specified payload string to the specified URI.
|
55
62
|
def post(uri:, payload:, headers: {}, limit: redirect_limit)
|
56
|
-
do_post_or_put(method: :post, uri: uri, payload: payload, headers: headers, limit: limit)
|
63
|
+
do_post_or_put(method: :post, uri: uri, payload: payload, headers: headers, limit: limit, timeout: timeout)
|
57
64
|
end
|
58
65
|
|
59
66
|
# Puts the specified payload string to the specified URI.
|
60
67
|
def put(uri:, payload:, headers: {}, limit: redirect_limit)
|
61
|
-
do_post_or_put(method: :put, uri: uri, payload: payload, headers: headers, limit: limit)
|
68
|
+
do_post_or_put(method: :put, uri: uri, payload: payload, headers: headers, limit: limit, timeout: timeout)
|
62
69
|
end
|
63
70
|
|
64
71
|
private
|
@@ -70,19 +77,20 @@ module Stash
|
|
70
77
|
}.freeze
|
71
78
|
end
|
72
79
|
|
73
|
-
def do_post_or_put(method:, uri:, payload:, headers:, limit:)
|
74
|
-
options = request_options(headers, limit, method, payload, uri)
|
80
|
+
def do_post_or_put(method:, uri:, payload:, headers:, limit:, timeout:)
|
81
|
+
options = request_options(headers, limit, method, payload, uri, timeout)
|
75
82
|
log_hash(options)
|
76
83
|
RestClient::Request.execute(**options)
|
77
84
|
end
|
78
85
|
|
79
|
-
def request_options(headers, limit, method, payload, uri)
|
86
|
+
def request_options(headers, limit, method, payload, uri, timeout)
|
80
87
|
options = {
|
81
88
|
method: method,
|
82
89
|
url: uri.to_s,
|
83
90
|
payload: payload,
|
84
91
|
headers: headers.merge(default_headers),
|
85
|
-
max_redirects: limit
|
92
|
+
max_redirects: limit,
|
93
|
+
timeout: timeout
|
86
94
|
}
|
87
95
|
options[:user] = username if username
|
88
96
|
options[:password] = password if password
|
@@ -7,21 +7,15 @@ module Stash
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def log_error(e)
|
10
|
-
|
11
|
-
log.error(response_to_log_msg(e.response))
|
12
|
-
else
|
13
|
-
log.error('Unable to log response')
|
14
|
-
end
|
10
|
+
log.error(to_log_msg(e))
|
15
11
|
end
|
16
12
|
|
17
|
-
def
|
18
|
-
[
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
'-----------------------------------------------------'
|
24
|
-
].join("\n")
|
13
|
+
def to_log_msg(e)
|
14
|
+
msg_lines = []
|
15
|
+
append_message(msg_lines, e)
|
16
|
+
append_response(msg_lines, e)
|
17
|
+
append_backtrace(msg_lines, e)
|
18
|
+
msg_lines.join("\n")
|
25
19
|
end
|
26
20
|
|
27
21
|
def log_hash(hash)
|
@@ -49,7 +43,11 @@ module Stash
|
|
49
43
|
end
|
50
44
|
|
51
45
|
def default_logger
|
52
|
-
|
46
|
+
LogUtils.create_default_logger($stdout, level)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.create_default_logger(io, level)
|
50
|
+
logger = Logger.new(io, 10, 1024 * 1024)
|
53
51
|
logger.level = level
|
54
52
|
logger.formatter = proc do |severity, datetime, progname, msg|
|
55
53
|
"#{datetime.to_time.utc} #{severity} -#{progname}- #{msg}\n"
|
@@ -57,6 +55,31 @@ module Stash
|
|
57
55
|
logger
|
58
56
|
end
|
59
57
|
|
58
|
+
private
|
59
|
+
|
60
|
+
def append_message(msg_lines, e)
|
61
|
+
msg_lines << if e.respond_to?(:message) && e.message
|
62
|
+
"message: #{e.message}"
|
63
|
+
else
|
64
|
+
e.to_s
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def append_response(msg_lines, e)
|
69
|
+
return unless e.respond_to?(:response) && e.response
|
70
|
+
response = e.response
|
71
|
+
msg_lines.unshift(*[
|
72
|
+
"code: #{response.code}",
|
73
|
+
'headers:', hash_to_log_msg(response.headers),
|
74
|
+
"body:\n#{response.body}"
|
75
|
+
])
|
76
|
+
end
|
77
|
+
|
78
|
+
def append_backtrace(msg_lines, e)
|
79
|
+
return unless e.respond_to?(:backtrace) && e.backtrace
|
80
|
+
msg_lines.unshift(*e.backtrace)
|
81
|
+
end
|
82
|
+
|
60
83
|
end
|
61
84
|
end
|
62
85
|
end
|
@@ -50,8 +50,20 @@ module Stash
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
it "gets the entry from the Edit-IRI in the Location: header if it isn't returned in the body" do
|
54
|
+
authorized_uri = collection_uri.sub('http://', "http://#{username}:#{password}@")
|
55
|
+
|
56
|
+
redirect_url = 'http://www.example.org/'
|
57
|
+
stub_request(:post, authorized_uri).to_return(status: 201, headers: { 'Location' => redirect_url })
|
58
|
+
stub_request(:get, redirect_url.sub('http://', "http://#{username}:#{password}@")).to_return(
|
59
|
+
body: '<entry xmlns="http://www.w3.org/2005/Atom"><id>http://merritt.cdlib.org/sword/v2/object/ark:/99999/fk4t157x4p</id><author><name>ucb_dash_submitter</name></author><generator uri="http://www.swordapp.org/" version="2.0" /><link href="http://merritt.cdlib.org/sword/v2/object/ark:/99999/fk4t157x4p" rel="edit" /><link href="http://merritt.cdlib.org/sword/v2/object/ark:/99999/fk4t157x4p" rel="http://purl.org/net/sword/terms/add" /><link href="http://merritt.cdlib.org/sword/v2/object/ark:/99999/fk4t157x4p" rel="edit-media" /><treatment xmlns="http://purl.org/net/sword/terms/">no treatment information available</treatment></entry>'
|
60
|
+
)
|
61
|
+
|
62
|
+
receipt = client.create(zipfile: zipfile, doi: doi)
|
63
|
+
expect(receipt).to be_a(DepositReceipt)
|
64
|
+
end
|
65
|
+
|
53
66
|
it 'returns the entry'
|
54
|
-
it "gets the entry from the Edit-IRI in the Location: header if it isn't returned in the body"
|
55
67
|
it 'forwards a success response'
|
56
68
|
|
57
69
|
it 'forwards a 4xx error' do
|
@@ -115,8 +127,15 @@ module Stash
|
|
115
127
|
end
|
116
128
|
end
|
117
129
|
|
118
|
-
it '
|
119
|
-
|
130
|
+
it 'follows redirects' do
|
131
|
+
edit_iri = "http://merritt.cdlib.org/sword/v2/object/#{doi}"
|
132
|
+
authorized_uri = edit_iri.sub('http://', "http://#{username}:#{password}@")
|
133
|
+
redirect_url = 'http://www.example.org/'
|
134
|
+
stub_request(:put, authorized_uri).to_return(status: 303, headers: { 'Location' => redirect_url })
|
135
|
+
stub_request(:get, redirect_url.sub('http://', "http://#{username}:#{password}@")).to_return(status: 200)
|
136
|
+
code = client.update(edit_iri: edit_iri, zipfile: zipfile)
|
137
|
+
expect(code).to eq(200)
|
138
|
+
end
|
120
139
|
|
121
140
|
it 'forwards a 4xx error' do
|
122
141
|
edit_iri = "http://merritt.cdlib.org/sword/v2/object/#{doi}"
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Stash
|
4
|
+
module Sword
|
5
|
+
describe LogUtils do
|
6
|
+
|
7
|
+
attr_reader :log_utils
|
8
|
+
attr_reader :rails_env
|
9
|
+
attr_reader :log_io
|
10
|
+
|
11
|
+
before(:all) { @rails_env = ENV['RAILS_ENV'] }
|
12
|
+
after(:all) { ENV['RAILS_ENV'] = rails_env }
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
@log_io = StringIO.new
|
16
|
+
@log_utils = Class.new { include LogUtils }.new
|
17
|
+
@log_utils.instance_variable_set(:@log, LogUtils.create_default_logger(@log_io, log_utils.level))
|
18
|
+
end
|
19
|
+
|
20
|
+
def log_str
|
21
|
+
@log_io.string
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sets the log level based on $RAILS_ENV' do
|
25
|
+
expected = {
|
26
|
+
'test' => Logger::DEBUG,
|
27
|
+
'development' => Logger::INFO,
|
28
|
+
'stage' => Logger::WARN,
|
29
|
+
'production' => Logger::WARN
|
30
|
+
}
|
31
|
+
expected.each do |env, lvl|
|
32
|
+
ENV['RAILS_ENV'] = env
|
33
|
+
expect(Class.new { include LogUtils }.new.level).to eq(lvl)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'logs an error response' do
|
38
|
+
code = 404
|
39
|
+
body = 'Your princess is in another castle'
|
40
|
+
headers = { 'Location' => 'http://example.org' }
|
41
|
+
message = 'I am the message'
|
42
|
+
|
43
|
+
response = instance_double(RestClient::Response)
|
44
|
+
expect(response).to receive(:code) { code }
|
45
|
+
expect(response).to receive(:headers) { headers }
|
46
|
+
expect(response).to receive(:body) { body }
|
47
|
+
|
48
|
+
error = RestClient::ExceptionWithResponse.new(response, 999)
|
49
|
+
error.message = message
|
50
|
+
|
51
|
+
log_utils.log_error(error)
|
52
|
+
expect(log_str).to include(code.to_s)
|
53
|
+
expect(log_str).to include(body)
|
54
|
+
headers.each do |k, v|
|
55
|
+
expect(log_str).to include("#{k}: #{v}")
|
56
|
+
end
|
57
|
+
expect(log_str).to include(message)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'logs an error with a nil response' do
|
61
|
+
message = 'I am the message'
|
62
|
+
error = RestClient::ExceptionWithResponse.new(nil, 999)
|
63
|
+
error.message = message
|
64
|
+
log_utils.log_error(error)
|
65
|
+
expect(log_str).to include(message)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'logs an error with a backtrace' do
|
69
|
+
backtrace = nil
|
70
|
+
begin
|
71
|
+
raise RestClient::ExceptionWithResponse.new(nil, 999)
|
72
|
+
rescue => e
|
73
|
+
backtrace = e.backtrace
|
74
|
+
log_utils.log_error(e)
|
75
|
+
end
|
76
|
+
expect(log_str).to include(backtrace.join("\n"))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stash-sword
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Moles
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -240,6 +240,7 @@ files:
|
|
240
240
|
- spec/unit/stash/sword2/http_helper_get_spec.rb
|
241
241
|
- spec/unit/stash/sword2/http_helper_post_spec.rb
|
242
242
|
- spec/unit/stash/sword2/http_helper_put_spec.rb
|
243
|
+
- spec/unit/stash/sword2/log_spec.rb
|
243
244
|
- spec/unit/stash/sword2/namespaces_spec.rb
|
244
245
|
- spec/unit/stash/sword2/sequence_io_spec.rb
|
245
246
|
- stash-sword.gemspec
|
@@ -263,7 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
263
264
|
version: '0'
|
264
265
|
requirements: []
|
265
266
|
rubyforge_project:
|
266
|
-
rubygems_version: 2.
|
267
|
+
rubygems_version: 2.6.8
|
267
268
|
signing_key:
|
268
269
|
specification_version: 4
|
269
270
|
summary: Stash SWORD 2.0 connector
|
@@ -278,6 +279,6 @@ test_files:
|
|
278
279
|
- spec/unit/stash/sword2/http_helper_get_spec.rb
|
279
280
|
- spec/unit/stash/sword2/http_helper_post_spec.rb
|
280
281
|
- spec/unit/stash/sword2/http_helper_put_spec.rb
|
282
|
+
- spec/unit/stash/sword2/log_spec.rb
|
281
283
|
- spec/unit/stash/sword2/namespaces_spec.rb
|
282
284
|
- spec/unit/stash/sword2/sequence_io_spec.rb
|
283
|
-
has_rdoc:
|