kataba 1.1.3 → 1.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/lib/kataba/fetcher.rb +12 -1
- data/lib/kataba.rb +51 -14
- metadata +12 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8ae88ae5dafc92e24f90d773300f44d096a5efb5d42e82c047e48c413ffcf852
|
|
4
|
+
data.tar.gz: 6954878cb4e2fb52646f294efda7a53dd0c11ac97e9a08554691d298ac5e961e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4be9c7f61034d3d0dbabcb65ccd56169f1f1f7e5aafeaa583a6cd5ab5cf348a5dac1c378d44a715f8b2aeecac8059a1af39a47a1cce53120bf2a5f3153d20630
|
|
7
|
+
data.tar.gz: bf9b63fcf72d6ae6c4ee1e515ff81854ae4f88d79b0a4496bdc2bdccd63fce49bcded29d8eb0fddc7c22f83860956716c7c114d101fe4e18a5b02e5f2e735c7e
|
data/lib/kataba/fetcher.rb
CHANGED
|
@@ -87,7 +87,7 @@ module Kataba
|
|
|
87
87
|
def request_with_redirects(uri, redirect_depth:)
|
|
88
88
|
raise FetchError, "too many redirects fetching #{@original_uri}" if redirect_depth > MAX_REDIRECTS
|
|
89
89
|
|
|
90
|
-
parsed =
|
|
90
|
+
parsed = parse_http_uri(uri)
|
|
91
91
|
http = Net::HTTP.new(parsed.host, parsed.port)
|
|
92
92
|
http.use_ssl = (parsed.scheme == 'https')
|
|
93
93
|
http.open_timeout = @open_timeout
|
|
@@ -116,6 +116,17 @@ module Kataba
|
|
|
116
116
|
end
|
|
117
117
|
end
|
|
118
118
|
|
|
119
|
+
# A bare filename parses as a URI with no host, and Net::HTTP then fails
|
|
120
|
+
# with NoMethodError, which no consumer's fetch-failure branch rescues.
|
|
121
|
+
def parse_http_uri(uri)
|
|
122
|
+
parsed = URI.parse(uri)
|
|
123
|
+
return parsed if parsed.is_a?(URI::HTTP) && parsed.host
|
|
124
|
+
|
|
125
|
+
raise FetchError, "not an absolute http(s) URI: #{uri}"
|
|
126
|
+
rescue URI::InvalidURIError => e
|
|
127
|
+
raise FetchError, "not a valid URI: #{uri} (#{e.message})"
|
|
128
|
+
end
|
|
129
|
+
|
|
119
130
|
def resolve_redirect(from, location)
|
|
120
131
|
raise FetchError, "redirect with no Location header from #{from}" if location.nil? || location.empty?
|
|
121
132
|
|
data/lib/kataba.rb
CHANGED
|
@@ -3,6 +3,8 @@ require 'tmpdir'
|
|
|
3
3
|
require 'digest/md5'
|
|
4
4
|
require 'fileutils'
|
|
5
5
|
require 'yaml'
|
|
6
|
+
require 'uri'
|
|
7
|
+
require 'set'
|
|
6
8
|
require 'kataba/fetcher'
|
|
7
9
|
|
|
8
10
|
module Kataba
|
|
@@ -116,12 +118,17 @@ module Kataba
|
|
|
116
118
|
|
|
117
119
|
private
|
|
118
120
|
|
|
119
|
-
def self.download_xsd(xsd_uri_array)
|
|
121
|
+
def self.download_xsd(xsd_uri_array, visited = Set.new)
|
|
120
122
|
new_xsd_uris = []
|
|
121
123
|
file_paths = []
|
|
122
124
|
|
|
123
125
|
# Download files
|
|
124
126
|
xsd_uri_array.each do |xsd_uri|
|
|
127
|
+
# Schemas may import each other (tdwg_dwc_simple.xsd and
|
|
128
|
+
# tdwg_dwc_extensions.xsd do), so fetch each URI once per call or the
|
|
129
|
+
# recursion never ends.
|
|
130
|
+
next unless visited.add?(xsd_uri)
|
|
131
|
+
|
|
125
132
|
uri_md5 = Digest::MD5.hexdigest(xsd_uri)
|
|
126
133
|
|
|
127
134
|
dir_name = "#{self.configuration.offline_storage}"
|
|
@@ -137,18 +144,22 @@ module Kataba
|
|
|
137
144
|
# Resolve mirror first, if configured, then fetch. Fetching BEFORE
|
|
138
145
|
# opening tmp_path means a failed network fetch can't leave an
|
|
139
146
|
# orphaned 0-byte .part on disk — the file simply isn't created.
|
|
140
|
-
|
|
147
|
+
mirror = nil
|
|
141
148
|
if !self.configuration.mirror_list.to_s.empty?
|
|
142
149
|
# YAML.load_file returns nil for a comments-only or empty file.
|
|
143
150
|
# Treat that as "no mirror configured" rather than NoMethodError.
|
|
144
151
|
mirror_list = YAML.load_file(self.configuration.mirror_list) || {}
|
|
145
|
-
mirror = mirror_list[xsd_uri]
|
|
146
|
-
|
|
152
|
+
mirror = mirror_list[xsd_uri].to_s
|
|
153
|
+
mirror = nil if mirror.empty?
|
|
147
154
|
end
|
|
148
155
|
|
|
149
|
-
body =
|
|
150
|
-
|
|
151
|
-
|
|
156
|
+
body = if mirror && !mirror.match?(%r{\Ahttps?://}i)
|
|
157
|
+
read_local_mirror(mirror)
|
|
158
|
+
else
|
|
159
|
+
Kataba::Fetcher.new(mirror || xsd_uri,
|
|
160
|
+
open_timeout: self.configuration.open_timeout,
|
|
161
|
+
read_timeout: self.configuration.read_timeout).fetch
|
|
162
|
+
end
|
|
152
163
|
|
|
153
164
|
# Write to a .part file first; only rename to the final cache path
|
|
154
165
|
# after we've confirmed the bytes parse as XML. Without this, a
|
|
@@ -165,20 +176,20 @@ module Kataba
|
|
|
165
176
|
end
|
|
166
177
|
|
|
167
178
|
File.rename(tmp_path, file_path)
|
|
168
|
-
file_paths << file_path
|
|
179
|
+
file_paths << [file_path, xsd_uri]
|
|
169
180
|
end
|
|
170
181
|
|
|
171
182
|
# Search inside for other schemaLocations
|
|
172
|
-
file_paths.each do |file_path|
|
|
173
|
-
new_xsd_uris
|
|
183
|
+
file_paths.each do |file_path, xsd_uri|
|
|
184
|
+
new_xsd_uris.concat(find_schemas(file_path, xsd_uri))
|
|
174
185
|
end
|
|
175
186
|
|
|
176
187
|
if !new_xsd_uris.reject(&:empty?).empty?
|
|
177
|
-
download_xsd(new_xsd_uris)
|
|
188
|
+
download_xsd(new_xsd_uris, visited)
|
|
178
189
|
end
|
|
179
190
|
end
|
|
180
191
|
|
|
181
|
-
def self.find_schemas(xml_file_path)
|
|
192
|
+
def self.find_schemas(xml_file_path, base_uri)
|
|
182
193
|
xsd_uri_array = []
|
|
183
194
|
|
|
184
195
|
# Open XML file
|
|
@@ -186,10 +197,11 @@ module Kataba
|
|
|
186
197
|
# search for schemaLocations
|
|
187
198
|
doc.xpath("//@schemaLocation").each do |node|
|
|
188
199
|
if !node.value.to_s.empty?
|
|
200
|
+
schema_uri = resolve_schema_location(node.value, base_uri)
|
|
189
201
|
# Add to array
|
|
190
|
-
xsd_uri_array <<
|
|
202
|
+
xsd_uri_array << schema_uri
|
|
191
203
|
# Get MD5
|
|
192
|
-
uri_md5 = Digest::MD5.hexdigest(
|
|
204
|
+
uri_md5 = Digest::MD5.hexdigest(schema_uri)
|
|
193
205
|
# Reassign attribute value
|
|
194
206
|
node.value = "#{uri_md5}.xsd"
|
|
195
207
|
end
|
|
@@ -200,4 +212,29 @@ module Kataba
|
|
|
200
212
|
|
|
201
213
|
return xsd_uri_array
|
|
202
214
|
end
|
|
215
|
+
|
|
216
|
+
# A mirror value that is not an http(s) URL is a file, so a consumer can
|
|
217
|
+
# ship a corrected schema with its own code. A relative path resolves
|
|
218
|
+
# against the mirror list's directory, never the working directory, which
|
|
219
|
+
# fetch_schema changes while it parses.
|
|
220
|
+
def self.read_local_mirror(path)
|
|
221
|
+
full_path = File.expand_path(path, File.dirname(self.configuration.mirror_list))
|
|
222
|
+
File.read(full_path)
|
|
223
|
+
rescue SystemCallError => e
|
|
224
|
+
raise Kataba::Fetcher::FetchError, "could not read mirror file #{full_path} (#{e.class})"
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# An absolute location is returned byte for byte. Its MD5 is the cache
|
|
228
|
+
# filename and the mirror_list key, so normalising it would orphan every
|
|
229
|
+
# cached schema and miss every mirror. A relative one resolves against the
|
|
230
|
+
# canonical URI of the schema importing it, never a mirror or a redirect
|
|
231
|
+
# target, so its cache name does not depend on where the bytes came from.
|
|
232
|
+
def self.resolve_schema_location(location, base_uri)
|
|
233
|
+
return location if URI.parse(location).absolute?
|
|
234
|
+
|
|
235
|
+
URI.join(base_uri, location).to_s
|
|
236
|
+
rescue URI::Error
|
|
237
|
+
# Left as written, so the Fetcher reports it as a FetchError.
|
|
238
|
+
location
|
|
239
|
+
end
|
|
203
240
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kataba
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cliff
|
|
@@ -14,56 +14,56 @@ dependencies:
|
|
|
14
14
|
name: nokogiri
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '1.19'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- -
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.19'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- -
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '0'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- -
|
|
38
|
+
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: minitest
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
|
-
- -
|
|
45
|
+
- - ">="
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
47
|
version: '0'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
|
-
- -
|
|
52
|
+
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: webmock
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- -
|
|
59
|
+
- - ">="
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
61
|
version: '0'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
|
-
- -
|
|
66
|
+
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '0'
|
|
69
69
|
description: Kataba allows for mirroring and offline storage of XSD files, to enhance
|
|
@@ -85,16 +85,16 @@ require_paths:
|
|
|
85
85
|
- lib
|
|
86
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
87
|
requirements:
|
|
88
|
-
- -
|
|
88
|
+
- - ">="
|
|
89
89
|
- !ruby/object:Gem::Version
|
|
90
90
|
version: '3.2'
|
|
91
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
|
-
- -
|
|
93
|
+
- - ">="
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
95
|
version: '0'
|
|
96
96
|
requirements: []
|
|
97
|
-
rubygems_version: 3.
|
|
97
|
+
rubygems_version: 3.2.33
|
|
98
98
|
signing_key:
|
|
99
99
|
specification_version: 4
|
|
100
100
|
summary: XML Schema Definition (XSD) mirroring and offline validation for Nokogiri
|