rack-s3 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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