stash-sword 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|