rack-archive-zip-extract 0.0.4 → 0.0.5
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/CHANGELOG.markdown +6 -0
- data/lib/rack/archive/zip/extract.rb +25 -9
- data/test/test_rack-archive-zip-extract.rb +23 -0
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 07bea84e8dd599718d60edf93979698acfa2ca84
|
|
4
|
+
data.tar.gz: 755f333cee8ead09814ef8d2253016ad5b9a4d0e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7d5e00114d0e8638ae5c7894ba507e5600c500d25be33f3f9528b5721996d7559501c7cca4983e1c0bbaed8e98e71150ba49a8104a7620c22fa80bbf66b85235
|
|
7
|
+
data.tar.gz: 661f0577924ef2c25f5199cfab991f4705f76b5d83dba65a0b243b02323ef762720a8c043571fdc9f2853521e7f655fbc8f056b4cb050aa81e6c40e3cca6f236
|
data/CHANGELOG.markdown
CHANGED
|
@@ -15,52 +15,63 @@ module Rack::Archive
|
|
|
15
15
|
# {Rack::Archive::Zip::Extract Rack::Archive::Zip::Extract} does not serve a zip file itself. Use Rack::File or so to do so.
|
|
16
16
|
class Extract
|
|
17
17
|
include Rack::Utils
|
|
18
|
+
extend Rack::Utils
|
|
18
19
|
|
|
19
20
|
SEPS = Rack::File::SEPS
|
|
20
21
|
DOT = '.'.freeze
|
|
21
22
|
DOUBLE_DOT = '..'.freeze
|
|
22
|
-
ALLOWED_METHODS = Rack::File::ALLOWED_VERBS.join(', ').freeze
|
|
23
|
-
ALLOW = 'Allow'.freeze
|
|
24
23
|
CONTENT_TYPE = 'Content-Type'.freeze
|
|
25
24
|
CONTENT_LENGTH = 'Content-Length'.freeze
|
|
26
25
|
IF_MODIFIED_SINCE = 'HTTP_IF_MODIFIED_SINCE'.freeze
|
|
27
26
|
LAST_MODIFIED = 'Last-Modified'.freeze
|
|
27
|
+
IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze
|
|
28
|
+
ETAG = 'ETag'.freeze
|
|
28
29
|
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
|
|
29
30
|
PATH_INFO = 'PATH_INFO'.freeze
|
|
31
|
+
METHOD_NOT_ALLOWED = [status_code(:method_not_allowd), {'Allow'.freeze => Rack::File::ALLOWED_VERBS.join(', ').freeze}, []]
|
|
32
|
+
NOT_FOUND = [status_code(:not_found), {}, []]
|
|
33
|
+
NOT_MODIFIED = [status_code(:not_modified), {}, []]
|
|
30
34
|
|
|
31
35
|
# @param root [Pathname, #to_path, String] path to document root
|
|
32
36
|
# @param extensions [Array<String>] extensions which is recognized as a zip file
|
|
37
|
+
# @param buffer_size [Integer] buffer size to read content, in bytes
|
|
33
38
|
# @raise [ArgumentError] if +root+ is not a directory
|
|
34
39
|
def initialize(root, extensions: %w[.zip], buffer_size: ExtractedFile::BUFFER_SIZE)
|
|
35
40
|
@root = root.kind_of?(Pathname) ? root : Pathname(root)
|
|
36
41
|
@root = @root.expand_path
|
|
37
|
-
@extensions = extensions.
|
|
42
|
+
@extensions = extensions.map {|extention| extention.dup.freeze}.lazy
|
|
38
43
|
@buffer_size = buffer_size
|
|
39
44
|
raise ArgumentError, "Not a directory: #{@root}" unless @root.directory?
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
def call(env)
|
|
43
|
-
return
|
|
48
|
+
return METHOD_NOT_ALLOWED unless Rack::File::ALLOWED_VERBS.include? env[REQUEST_METHOD]
|
|
44
49
|
|
|
45
50
|
path_info = unescape(env[PATH_INFO])
|
|
46
51
|
file = @extensions.map {|ext|
|
|
47
52
|
zip_file, inner_path = find_zip_file_and_inner_path(path_info, ext)
|
|
48
53
|
extract_file(zip_file, inner_path)
|
|
49
54
|
}.select {|file| file}.first
|
|
50
|
-
return
|
|
55
|
+
return NOT_FOUND if file.nil?
|
|
51
56
|
|
|
52
57
|
if_modified_since = env[IF_MODIFIED_SINCE]
|
|
53
58
|
if_modified_since = Time.parse(if_modified_since) if if_modified_since
|
|
54
|
-
|
|
59
|
+
|
|
60
|
+
if_none_match = env[IF_NONE_MATCH]
|
|
61
|
+
etag = file.name.hash.to_s(16) + file.mtime.hash.to_s(16)
|
|
62
|
+
|
|
63
|
+
if if_modified_since && file.mtime <= if_modified_since or
|
|
64
|
+
if_none_match && if_none_match == etag
|
|
55
65
|
file.close
|
|
56
|
-
|
|
66
|
+
NOT_MODIFIED
|
|
57
67
|
else
|
|
58
68
|
[
|
|
59
69
|
status_code(:ok),
|
|
60
70
|
{
|
|
61
71
|
CONTENT_TYPE => Rack::Mime.mime_type(::File.extname(path_info)),
|
|
62
72
|
CONTENT_LENGTH => file.size.to_s,
|
|
63
|
-
LAST_MODIFIED => file.mtime.httpdate
|
|
73
|
+
LAST_MODIFIED => file.mtime.httpdate,
|
|
74
|
+
ETAG => etag
|
|
64
75
|
},
|
|
65
76
|
file
|
|
66
77
|
]
|
|
@@ -83,7 +94,7 @@ module Rack::Archive
|
|
|
83
94
|
|
|
84
95
|
# @param zip_file_path [Pathname] path to zip file
|
|
85
96
|
# @param inner_path [String] path to file in zip archive
|
|
86
|
-
# @return [
|
|
97
|
+
# @return [ExtractedFile]
|
|
87
98
|
# @return [nil] if +zip_file_path+ is nil or +inner_path+ is empty
|
|
88
99
|
# @return [nil] if +inner_path+ doesn't exist in zip archive
|
|
89
100
|
def extract_file(zip_file_path, inner_path)
|
|
@@ -115,6 +126,7 @@ module Rack::Archive
|
|
|
115
126
|
|
|
116
127
|
# @param archive [Zip::Archive]
|
|
117
128
|
# @param path [String]
|
|
129
|
+
# @param buffer_size [Integer]
|
|
118
130
|
# @raise ArgumentError when +archive+ already closed
|
|
119
131
|
def initialize(archive, path, buffer_size=BUFFER_SIZE)
|
|
120
132
|
raise ArgumentError, 'archive already closed' unless archive.open?
|
|
@@ -129,6 +141,10 @@ module Rack::Archive
|
|
|
129
141
|
end
|
|
130
142
|
end
|
|
131
143
|
|
|
144
|
+
def name
|
|
145
|
+
@file.name
|
|
146
|
+
end
|
|
147
|
+
|
|
132
148
|
def mtime
|
|
133
149
|
@file.mtime
|
|
134
150
|
end
|
|
@@ -43,6 +43,29 @@ class TestRackArchiveZipExtract < Test::Unit::TestCase
|
|
|
43
43
|
assert_empty response.body
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
def test_request_to_file_in_zip_returns_etag
|
|
47
|
+
response = request('/sample/sample.txt')
|
|
48
|
+
|
|
49
|
+
assert_not_nil response['ETag']
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_request_to_old_file_with_etag_returns_not_modified
|
|
53
|
+
path = '/sample/sample.txt'
|
|
54
|
+
etag = request(path)['ETag']
|
|
55
|
+
|
|
56
|
+
response = request(path, @zip, {'HTTP_IF_NONE_MATCH' => etag})
|
|
57
|
+
|
|
58
|
+
assert_equal 304, response.status
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_request_to_old_file_with_etag_returns_no_content
|
|
62
|
+
path = '/sample/sample.txt'
|
|
63
|
+
etag = request(path)['ETag']
|
|
64
|
+
response = request(path, @zip, {'HTTP_IF_NONE_MATCH' => etag})
|
|
65
|
+
|
|
66
|
+
assert_empty response.body
|
|
67
|
+
end
|
|
68
|
+
|
|
46
69
|
class TestStatusCode < self
|
|
47
70
|
data(
|
|
48
71
|
'file in zip' => [200, '/sample/sample.txt'],
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack-archive-zip-extract
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- KITAITI Makoto
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-
|
|
11
|
+
date: 2014-05-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '2'
|
|
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
|
-
version: '
|
|
54
|
+
version: '2'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: test-unit-notify
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -114,7 +114,7 @@ files:
|
|
|
114
114
|
- test/fixtures/sample-zip/sample.xml
|
|
115
115
|
- test/fixtures/sample-zip/subdir/sample.txt
|
|
116
116
|
- test/test_rack-archive-zip-extract.rb
|
|
117
|
-
homepage:
|
|
117
|
+
homepage: http://rubydoc.info/gems/rack-archive-zip-extract/
|
|
118
118
|
licenses:
|
|
119
119
|
- MIT
|
|
120
120
|
metadata: {}
|
|
@@ -134,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
134
134
|
version: '0'
|
|
135
135
|
requirements: []
|
|
136
136
|
rubyforge_project:
|
|
137
|
-
rubygems_version: 2.2.
|
|
137
|
+
rubygems_version: 2.2.2
|
|
138
138
|
signing_key:
|
|
139
139
|
specification_version: 4
|
|
140
140
|
summary: Zip file server
|