rack-s3 0.0.1 → 0.0.2

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.
data/Gemfile.lock CHANGED
@@ -8,19 +8,27 @@ PATH
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
+ addressable (2.2.3)
11
12
  aws-s3 (0.6.2)
12
13
  builder
13
14
  mime-types
14
15
  xml-simple
15
16
  builder (3.0.0)
17
+ crack (0.1.8)
16
18
  mime-types (1.16)
17
19
  rack (1.2.1)
20
+ shoulda (2.11.3)
21
+ vcr (1.5.0)
22
+ webmock (1.6.2)
23
+ addressable (>= 2.2.2)
24
+ crack (>= 0.1.7)
18
25
  xml-simple (1.0.13)
19
26
 
20
27
  PLATFORMS
21
28
  ruby
22
29
 
23
30
  DEPENDENCIES
24
- aws-s3
25
- rack
26
31
  rack-s3!
32
+ shoulda
33
+ vcr
34
+ webmock
data/lib/rack/s3.rb CHANGED
@@ -6,7 +6,6 @@ module Rack
6
6
 
7
7
  def initialize(app, options={})
8
8
  @app = app
9
- @prefix = options[:prefix]
10
9
  @bucket = options[:bucket]
11
10
 
12
11
  AWS::S3::Base.establish_connection!(
@@ -20,13 +19,7 @@ module Rack
20
19
 
21
20
  def _call(env)
22
21
  @env = env
23
-
24
- if can_serve?
25
- [ 200, headers, object.value ]
26
- else
27
- @app.call env
28
- end
29
-
22
+ [ 200, headers, object.value ]
30
23
  rescue AWS::S3::NoSuchKey
31
24
  not_found
32
25
  end
@@ -42,16 +35,12 @@ module Rack
42
35
  }
43
36
  end
44
37
 
45
- def can_serve?
46
- path_info.index(@prefix) == 0
47
- end
48
-
49
38
  def path_info
50
39
  @env['PATH_INFO']
51
40
  end
52
41
 
53
42
  def path
54
- path_info.split('/').last
43
+ path_info[0...1] == '/' ? path_info[1..-1] : path_info
55
44
  end
56
45
 
57
46
  def object
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class S3
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
data/rack-s3.gemspec CHANGED
@@ -15,6 +15,10 @@ Gem::Specification.new do |s|
15
15
  s.add_dependency 'aws-s3'
16
16
  s.add_dependency 'rack'
17
17
 
18
+ s.add_development_dependency 'shoulda'
19
+ s.add_development_dependency 'webmock'
20
+ s.add_development_dependency 'vcr'
21
+
18
22
  s.files = `git ls-files`.split("\n")
19
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
24
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
data/test/rack_s3_test.rb CHANGED
@@ -1,50 +1,92 @@
1
1
  require 'test_helper'
2
- require 'rack/mock'
3
-
4
- class DummyApp
5
- def call(env)
6
- [ 200, {}, [ "Hello World" ]]
7
- end
8
- end
9
2
 
10
3
  class RackS3Test < Test::Unit::TestCase
11
4
 
12
5
  def app
13
- # HACK: Use your S3 credentials to run the test suite. Should use a
14
- # recording library like VCR.
15
- options = { :prefix => '/s3',
16
- :bucket => 'rack-s3',
17
- :access_key_id => 'insert_access_key_here',
18
- :secret_access_key => 'insert_secret_here' }
19
-
20
- Rack::MockRequest.new Rack::S3.new(DummyApp.new, options)
6
+ options = { :bucket => 'rack-s3',
7
+ :access_key_id => 'abc123',
8
+ :secret_access_key => 'abc123' }
9
+
10
+ Rack::Builder.new do
11
+ use Rack::S3, options
12
+ run lambda { [ 200, {}, [ "Hello World" ]] }
13
+ end
14
+ end
15
+
16
+ def mapped_app
17
+ # #app isn't available inside the block below.
18
+ unmapped_app = app
19
+
20
+ Rack::Builder.new do
21
+ map '/mapped/app' do
22
+ run unmapped_app
23
+ end
24
+ end
25
+ end
26
+
27
+
28
+ context 'A request for a nonexistent key' do
29
+ subject do
30
+ VCR.use_cassette 'not_found' do
31
+ Rack::MockRequest.new(app).get '/not_found.png'
32
+ end
33
+ end
34
+
35
+ should 'render a not found response' do
36
+ assert_equal 404, subject.status
37
+ assert_equal "File not found: /not_found.png\n", subject.body
38
+
39
+ assert_equal 'text/plain', subject.headers['Content-Type']
40
+ assert_equal '31', subject.headers['Content-Length']
41
+ end
21
42
  end
22
43
 
23
- def test_serve_files_from_s3
24
- response = app.get '/s3/clear.png'
44
+ context 'A request for a key' do
45
+ subject do
46
+ VCR.use_cassette 'clear' do
47
+ Rack::MockRequest.new(app).get '/clear.png'
48
+ end
49
+ end
25
50
 
26
- assert_equal 200, response.status
27
- assert_equal 'public; max-age=2592000', response.headers['Cache-Control']
28
- assert_not_nil response.body
51
+ should 'render the file' do
52
+ assert_equal 200, subject.status
53
+ assert_equal 'public; max-age=2592000', subject.headers['Cache-Control']
54
+ assert_not_nil subject.body
29
55
 
30
- %w(Content-Type Last-Modified Last-Modified Etag).each do |header|
31
- assert_not_nil response.headers[header]
56
+ %w(Content-Type Last-Modified Last-Modified Etag).each do |header|
57
+ assert_not_nil subject.headers[header]
58
+ end
32
59
  end
33
60
  end
34
61
 
35
- def test_ignore_requests_outside_of_prefix
36
- response = app.get '/ignore_me'
62
+ context 'A request for a nested key' do
63
+ subject do
64
+ VCR.use_cassette 'nested_clear' do
65
+ Rack::MockRequest.new(app).get '/very/important/files/clear.png'
66
+ end
67
+ end
68
+
69
+ should 'render the file' do
70
+ assert_equal 200, subject.status
71
+ assert_equal 'public; max-age=2592000', subject.headers['Cache-Control']
72
+ assert_not_nil subject.body
37
73
 
38
- assert_equal 'Hello World', response.body
74
+ %w(Content-Type Last-Modified Last-Modified Etag).each do |header|
75
+ assert_not_nil subject.headers[header]
76
+ end
77
+ end
39
78
  end
40
79
 
41
- def test_return_not_found_for_nonexistent_files
42
- response = app.get '/s3/nil.png'
80
+ context 'A request to a mapped app' do
81
+ subject do
82
+ VCR.use_cassette 'clear' do
83
+ Rack::MockRequest.new(mapped_app).get '/mapped/app/clear.png'
84
+ end
85
+ end
43
86
 
44
- assert_equal 404, response.status
45
- assert_equal "File not found: /s3/nil.png\n", response.body
46
- assert_equal 'text/plain', response.headers['Content-Type']
47
- assert_equal '28', response.headers['Content-Length']
87
+ should 'render the file' do
88
+ assert_equal 200, subject.status
89
+ end
48
90
  end
49
91
 
50
92
  end
data/test/test_helper.rb CHANGED
@@ -4,7 +4,15 @@ require 'test/unit'
4
4
  require 'bundler/setup'
5
5
  Bundler.require :development
6
6
 
7
+ require 'rack/mock'
7
8
  require 'rack/s3'
8
9
 
9
10
  class Test::Unit::TestCase
11
+
12
+ VCR.config do |c|
13
+ c.cassette_library_dir = 'test/vcr_cassettes'
14
+ c.stub_with :webmock
15
+ c.default_cassette_options = { :record => :none }
16
+ end
17
+
10
18
  end
@@ -0,0 +1,94 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://s3.amazonaws.com:80/rack-s3?marker=clear.pnf&max-keys=1
6
+ body:
7
+ headers:
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 200
11
+ message: OK
12
+ headers:
13
+ x-amz-id-2:
14
+ - iIjcmkNXzlg1zNQXmrO+gglqBmJR6znWyQf3nBwiRgfxIaLhCJDzIySgjoCQPhm2
15
+ content-type:
16
+ - application/xml
17
+ server:
18
+ - AmazonS3
19
+ date:
20
+ - Tue, 25 Jan 2011 21:06:13 GMT
21
+ x-amz-request-id:
22
+ - AAAAAAAAAAAAAAAA
23
+ transfer-encoding:
24
+ - chunked
25
+ body: |-
26
+ <?xml version="1.0" encoding="UTF-8"?>
27
+ <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Name>rack-s3</Name><Prefix></Prefix><Marker>clear.pnf</Marker><MaxKeys>1</MaxKeys><IsTruncated>true</IsTruncated><Contents><Key>clear.png</Key><LastModified>2011-01-22T01:40:19.000Z</LastModified><ETag>&quot;71a50dbba44c78128b221b7df7bb51f1&quot;</ETag><Size>95</Size><Owner><ID>abc123</ID><DisplayName>rack-s3</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>
28
+ http_version: "1.1"
29
+ - !ruby/struct:VCR::HTTPInteraction
30
+ request: !ruby/struct:VCR::Request
31
+ method: :head
32
+ uri: http://s3.amazonaws.com:80/rack-s3/clear.png
33
+ body:
34
+ headers:
35
+ response: !ruby/struct:VCR::Response
36
+ status: !ruby/struct:VCR::ResponseStatus
37
+ code: 200
38
+ message: OK
39
+ headers:
40
+ etag:
41
+ - "\"71a50dbba44c78128b221b7df7bb51f1\""
42
+ last-modified:
43
+ - Sat, 22 Jan 2011 01:40:19 GMT
44
+ x-amz-id-2:
45
+ - 5DNVaHC4B0cbQqBc10aCulfozqKEpJPLo6SNcBcFRkZLD4+cZRNY9TBXe5KLEJDK
46
+ content-type:
47
+ - image/png
48
+ server:
49
+ - AmazonS3
50
+ date:
51
+ - Tue, 25 Jan 2011 21:06:13 GMT
52
+ content-length:
53
+ - "95"
54
+ x-amz-request-id:
55
+ - BBBBBBBBBBBBBBBB
56
+ accept-ranges:
57
+ - bytes
58
+ body:
59
+ http_version: "1.1"
60
+ - !ruby/struct:VCR::HTTPInteraction
61
+ request: !ruby/struct:VCR::Request
62
+ method: :get
63
+ uri: http://s3.amazonaws.com:80/rack-s3/clear.png
64
+ body:
65
+ headers:
66
+ response: !ruby/struct:VCR::Response
67
+ status: !ruby/struct:VCR::ResponseStatus
68
+ code: 200
69
+ message: OK
70
+ headers:
71
+ etag:
72
+ - "\"71a50dbba44c78128b221b7df7bb51f1\""
73
+ last-modified:
74
+ - Sat, 22 Jan 2011 01:40:19 GMT
75
+ x-amz-id-2:
76
+ - VHSXty5O3M9vnhiRRL3OzbCfrNIB2BA35K4DtJ9AIO5UXeYHHTmDTzCjYVUTi3XF
77
+ content-type:
78
+ - image/png
79
+ server:
80
+ - AmazonS3
81
+ date:
82
+ - Tue, 25 Jan 2011 21:06:13 GMT
83
+ content-length:
84
+ - "95"
85
+ x-amz-request-id:
86
+ - CCCCCCCCCCCCCCCC
87
+ accept-ranges:
88
+ - bytes
89
+ body: !binary |
90
+ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACn
91
+ ej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVO
92
+ RK5CYII=
93
+
94
+ http_version: "1.1"
@@ -0,0 +1,94 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://s3.amazonaws.com:80/rack-s3?marker=very/important/files/clear.pnf&max-keys=1
6
+ body:
7
+ headers:
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 200
11
+ message: OK
12
+ headers:
13
+ x-amz-id-2:
14
+ - ffuJcBHfzAJ8xBN78wtnMwkXLLIxj9jOhV9AN0ShCLRpsiZVgKbWGts58jNTWj2A
15
+ content-type:
16
+ - application/xml
17
+ server:
18
+ - AmazonS3
19
+ date:
20
+ - Tue, 25 Jan 2011 21:34:08 GMT
21
+ x-amz-request-id:
22
+ - FEFB96BBB722B0FA
23
+ transfer-encoding:
24
+ - chunked
25
+ body: |-
26
+ <?xml version="1.0" encoding="UTF-8"?>
27
+ <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Name>rack-s3</Name><Prefix></Prefix><Marker>very/important/files/clear.pnf</Marker><MaxKeys>1</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>very/important/files/clear.png</Key><LastModified>2011-01-25T21:26:16.000Z</LastModified><ETag>&quot;71a50dbba44c78128b221b7df7bb51f1&quot;</ETag><Size>95</Size><Owner><ID>abc123</ID><DisplayName>rack-s3</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>
28
+ http_version: "1.1"
29
+ - !ruby/struct:VCR::HTTPInteraction
30
+ request: !ruby/struct:VCR::Request
31
+ method: :head
32
+ uri: http://s3.amazonaws.com:80/rack-s3/very/important/files/clear.png
33
+ body:
34
+ headers:
35
+ response: !ruby/struct:VCR::Response
36
+ status: !ruby/struct:VCR::ResponseStatus
37
+ code: 200
38
+ message: OK
39
+ headers:
40
+ etag:
41
+ - "\"71a50dbba44c78128b221b7df7bb51f1\""
42
+ last-modified:
43
+ - Tue, 25 Jan 2011 21:26:16 GMT
44
+ x-amz-id-2:
45
+ - lbRqqCOq4dt4LICQKxbE+zWaayYw3+4A+8RjijAYIe9uW+NgeEDRdsDo9bTJcIoC
46
+ content-type:
47
+ - image/png
48
+ server:
49
+ - AmazonS3
50
+ date:
51
+ - Tue, 25 Jan 2011 21:34:08 GMT
52
+ content-length:
53
+ - "95"
54
+ x-amz-request-id:
55
+ - 5E4F5037D17C276D
56
+ accept-ranges:
57
+ - bytes
58
+ body:
59
+ http_version: "1.1"
60
+ - !ruby/struct:VCR::HTTPInteraction
61
+ request: !ruby/struct:VCR::Request
62
+ method: :get
63
+ uri: http://s3.amazonaws.com:80/rack-s3/very/important/files/clear.png
64
+ body:
65
+ headers:
66
+ response: !ruby/struct:VCR::Response
67
+ status: !ruby/struct:VCR::ResponseStatus
68
+ code: 200
69
+ message: OK
70
+ headers:
71
+ etag:
72
+ - "\"71a50dbba44c78128b221b7df7bb51f1\""
73
+ last-modified:
74
+ - Tue, 25 Jan 2011 21:26:16 GMT
75
+ x-amz-id-2:
76
+ - QYMU8xe/VbyO0TOaBIjxdekTAiPd47sWRFg+GfKwD7QweTyEouln1W/7hDj3F1cr
77
+ content-type:
78
+ - image/png
79
+ server:
80
+ - AmazonS3
81
+ date:
82
+ - Tue, 25 Jan 2011 21:34:09 GMT
83
+ content-length:
84
+ - "95"
85
+ x-amz-request-id:
86
+ - 0BCD2B062BA0FAD6
87
+ accept-ranges:
88
+ - bytes
89
+ body: !binary |
90
+ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACn
91
+ ej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVO
92
+ RK5CYII=
93
+
94
+ http_version: "1.1"
@@ -0,0 +1,28 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://s3.amazonaws.com:80/rack-s3?marker=not_found.pnf&max-keys=1
6
+ body:
7
+ headers:
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 200
11
+ message: OK
12
+ headers:
13
+ x-amz-id-2:
14
+ - abc123
15
+ content-type:
16
+ - application/xml
17
+ server:
18
+ - AmazonS3
19
+ date:
20
+ - Tue, 25 Jan 2011 20:56:58 GMT
21
+ x-amz-request-id:
22
+ - abc123
23
+ transfer-encoding:
24
+ - chunked
25
+ body: |-
26
+ <?xml version="1.0" encoding="UTF-8"?>
27
+ <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Name>rack-s3</Name><Prefix></Prefix><Marker>not_found.pnf</Marker><MaxKeys>1</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>test.png</Key><LastModified>2011-01-22T02:59:53.000Z</LastModified><ETag>&quot;71a50dbba44c78128b221b7df7bb51f1&quot;</ETag><Size>47173</Size><Owner><ID>abc123</ID><DisplayName>rack-s3</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>
28
+ http_version: "1.1"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-s3
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Larry Marburger
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-21 00:00:00 -05:00
18
+ date: 2011-01-26 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -46,6 +46,48 @@ dependencies:
46
46
  version: "0"
47
47
  type: :runtime
48
48
  version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: shoulda
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: webmock
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: vcr
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :development
90
+ version_requirements: *id005
49
91
  description: Serve files from an S3 bucket as if they were local assets similar to Rack::Static.
50
92
  email:
51
93
  - larry@marburger.cc
@@ -67,6 +109,9 @@ files:
67
109
  - rack-s3.gemspec
68
110
  - test/rack_s3_test.rb
69
111
  - test/test_helper.rb
112
+ - test/vcr_cassettes/clear.yml
113
+ - test/vcr_cassettes/nested_clear.yml
114
+ - test/vcr_cassettes/not_found.yml
70
115
  has_rdoc: true
71
116
  homepage: http://developmentastic.com
72
117
  licenses: []
@@ -104,3 +149,6 @@ summary: A Rack::Static like middleware for serving assets from S3
104
149
  test_files:
105
150
  - test/rack_s3_test.rb
106
151
  - test/test_helper.rb
152
+ - test/vcr_cassettes/clear.yml
153
+ - test/vcr_cassettes/nested_clear.yml
154
+ - test/vcr_cassettes/not_found.yml