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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8f335e345e79786674c599d49801cfab192613ec
4
- data.tar.gz: 05268821dfdf5582e97e7580accbcf2cbe9a187b
3
+ metadata.gz: 07bea84e8dd599718d60edf93979698acfa2ca84
4
+ data.tar.gz: 755f333cee8ead09814ef8d2253016ad5b9a4d0e
5
5
  SHA512:
6
- metadata.gz: 0d32ed10d8c653fbc13463163c94198af348cfdfcd43b9e916cf92762def4eafe2419a47e40e1a2a618ffcfdd41d9f078be5a98202d649e3b3ce3a56511e7f96
7
- data.tar.gz: 61a4b7dc23f899ce983976f0d334b8bca21459813a6aab5e43e3b69c7cf41789aefa9bda5f139640b7c455aa48174c7e343b05eb54d0ee016195dc7f99c75ae0
6
+ metadata.gz: 7d5e00114d0e8638ae5c7894ba507e5600c500d25be33f3f9528b5721996d7559501c7cca4983e1c0bbaed8e98e71150ba49a8104a7620c22fa80bbf66b85235
7
+ data.tar.gz: 661f0577924ef2c25f5199cfab991f4705f76b5d83dba65a0b243b02323ef762720a8c043571fdc9f2853521e7f655fbc8f056b4cb050aa81e6c40e3cca6f236
data/CHANGELOG.markdown CHANGED
@@ -1,6 +1,12 @@
1
1
  CHANGELOG
2
2
  =========
3
3
 
4
+ 0.0.5
5
+ -----
6
+
7
+ * [BUG FIX]Duplicate extensions before freezing
8
+ * Send ETag header
9
+
4
10
  0.0.4
5
11
  -----
6
12
 
@@ -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.each {|extention| extention.freeze}.lazy
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 [status_code(:method_not_allowd), {ALLOW => ALLOWED_METHODS}, []] unless Rack::File::ALLOWED_VERBS.include? env[REQUEST_METHOD]
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 [status_code(:not_found), {}, []] if file.nil?
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
- if if_modified_since and file.mtime <= if_modified_since
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
- [status_code(:not_modified), {}, []]
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 [Zip::File]
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
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-01-26 00:00:00.000000000 Z
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: '1'
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: '1'
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: https://github.com/KitaitiMakoto/rack-archive-zip-extract
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.0
137
+ rubygems_version: 2.2.2
138
138
  signing_key:
139
139
  specification_version: 4
140
140
  summary: Zip file server