s3_proxy 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dea44cf361b902f466809821fe30b411db50add3
4
- data.tar.gz: 8d929051a8382e50fad93796c980613c9e140f1d
3
+ metadata.gz: b87ae0701382cfcc91e7b233bd68ecef70546677
4
+ data.tar.gz: 5c6344cbac68b8b9b06b5a032aa9d0db5e4a1821
5
5
  SHA512:
6
- metadata.gz: cb0718bf8606acda33658d475862aff4482bdf59afb2fffb08a86da53ae421a266054de9c32e38c9d09c8bd71608c87294e08703e6df0c5d53e9e1372c94ce31
7
- data.tar.gz: 4cb738cac629cd46beec034f40286790f4c5cb738a6519f10586f50daba3d86f5e8d2667d474739fb93df127dd2ae885f061ec34f3e23b9b21630e5c6733b252
6
+ metadata.gz: 636b2f85af7915558cae9107de37cc2498e961909af4821ca2621bbaa531ad3b2711a01a33b7f00f6053f63faa0a352043807e7956279d6ad80174d3dcd9a79c
7
+ data.tar.gz: 3f42b9f14ac02405ca8489f76211f01f4e8a1c665f75dbe29463dbb122875f630f43aa0f182d5b4de4836caa4933d0f6dad11260dbd5768178517af80572cb45
@@ -8,28 +8,60 @@ module S3Proxy
8
8
  end
9
9
 
10
10
  def call(env)
11
- return Errors.method_not_allowed unless env['REQUEST_METHOD'] == 'GET'
11
+ return Errors.method_not_allowed unless %w(GET HEAD).include?(env['REQUEST_METHOD'])
12
12
  return Errors.not_found if env['PATH_INFO'].empty?
13
13
 
14
- _, bucket, key = env['PATH_INFO'].split('/', 3)
15
- path = {bucket: bucket, key: key}
14
+ # When used as a forward proxy
15
+ if env['HTTP_HOST'] =~ /(.+)\.s3\.amazonaws\.com/
16
+ bucket = $1
17
+ _, key = env['PATH_INFO'].split('/', 2)
18
+ else
19
+ _, bucket, key = env['PATH_INFO'].split('/', 3)
20
+ end
21
+
22
+ return Errors.not_found unless bucket && key
23
+
24
+ req = {bucket: bucket, key: key}
25
+
26
+ req[:if_match] = env['HTTP_IF_MATCH'] if env['HTTP_IF_MATCH']
27
+ req[:if_none_match] = env['HTTP_IF_NONE_MATCH'] if env['HTTP_IF_NONE_MATCH']
28
+ req[:if_modified_since] = env['HTTP_IF_MODIFIED_SINCE'] if env['HTTP_IF_MODIFIED_SINCE']
29
+ req[:if_unmodified_since] = env['HTTP_IF_UNMODIFIED_SINCE'] if env['HTTP_UNMODIFIED_SINCE']
30
+
31
+ head = s3.head_object(req)
16
32
 
17
- head = s3.head_object(path)
18
33
  return Errors.not_found unless head
19
34
 
20
- if env['rack.hijack?']
21
- hijack env, path, head
22
- else
23
- gentle env, path, head
35
+ case env['REQUEST_METHOD']
36
+ when 'HEAD'
37
+ gentle env, req, head
38
+ when 'GET'
39
+ if env['rack.hijack?']
40
+ hijack env, req, head
41
+ else
42
+ gentle env, req, head
43
+ end
24
44
  end
25
45
 
26
- rescue Aws::S3::Errors::NoSuchKey
46
+ rescue Aws::S3::Errors::NoSuchKey, Aws::S3::Errors::NotFound
27
47
  return Errors.not_found
48
+
49
+ rescue Aws::S3::Errors::NotModified
50
+ return Errors.not_modified
51
+
52
+ rescue Aws::S3::Errors::PreconditionFailed
53
+ return Errors.precondition_failed
54
+
55
+ rescue NameError => e
56
+ # https://github.com/aws/aws-sdk-core-ruby/pull/65
57
+ raise e unless e.message == "wrong constant name 412Error"
58
+
59
+ return Errors.precondition_failed
28
60
  end
29
61
 
30
62
  private
31
63
 
32
- def hijack(env, path, head)
64
+ def hijack(env, request, head)
33
65
  env['rack.hijack'].call
34
66
 
35
67
  io = env['rack.hijack_io']
@@ -39,31 +71,45 @@ module S3Proxy
39
71
  io.write "Connection: close\r\n"
40
72
  io.write "Content-Type: #{head.content_type}\r\n"
41
73
  io.write "Content-Length: #{head.content_length}\r\n"
74
+ io.write "ETag: #{head.etag}\r\n"
75
+ io.write "Last-Modified: #{head.last_modified}\r\n"
42
76
  io.write "\r\n"
43
77
  io.flush
44
78
 
45
- s3.get_object(path, target: io)
79
+ s3.get_object(request, target: io)
46
80
  ensure
47
81
  io.close
48
82
  end
49
83
  return [200, {}, ['']]
50
84
  end
51
85
 
52
- def gentle(env, path, head)
53
- fiber = Fiber.new do
54
- s3.get_object(path) do |chunk|
55
- Fiber.yield(chunk)
86
+ def gentle(env, request, head)
87
+ case env['REQUEST_METHOD']
88
+ when 'GET'
89
+ fiber = Fiber.new do
90
+ s3.get_object(request) do |chunk|
91
+ Fiber.yield(chunk)
92
+ end
93
+ Fiber.yield(nil)
56
94
  end
57
- Fiber.yield(nil)
58
- end
59
95
 
60
- body = Enumerator.new do |y|
61
- while n = fiber.resume
62
- y << n
96
+ body = Enumerator.new do |y|
97
+ while n = fiber.resume
98
+ y << n
99
+ end
63
100
  end
101
+ when 'HEAD'
102
+ body = ['']
64
103
  end
65
104
 
66
- [200, {'Content-Type' => head.content_type, 'Content-Length' => head.content_length.to_s}, body]
105
+ headers = {
106
+ 'Content-Type' => head.content_type,
107
+ 'Content-Length' => head.content_length.to_s,
108
+ 'Last-Modified' => head.last_modified,
109
+ 'ETag' => head.etag,
110
+ }
111
+
112
+ [200, headers, body]
67
113
  end
68
114
 
69
115
  def s3
@@ -84,6 +130,14 @@ module S3Proxy
84
130
  [403, {'Content-Type' => 'text/plain'}, ["forbidden"]]
85
131
  end
86
132
 
133
+ def precondition_failed
134
+ [412, {'Content-Type' => 'text/plain'}, ["precondition failed"]]
135
+ end
136
+
137
+ def not_modified
138
+ [304, {'Content-Type' => 'text/plain'}, ["not modified"]]
139
+ end
140
+
87
141
  def unknown(code)
88
142
  [code, {'Content-Type' => 'text/plain'}, ["Error: #{code}"]]
89
143
  end
@@ -1,3 +1,3 @@
1
1
  module S3Proxy
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3_proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shota Fukumori (sora_h)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-10 00:00:00.000000000 Z
11
+ date: 2014-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -122,3 +122,4 @@ signing_key:
122
122
  specification_version: 4
123
123
  summary: S3 reverse proxy rack app that accepts multiple buckets
124
124
  test_files: []
125
+ has_rdoc: