fakes3 1.2.1 → 1.3.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
- SHA1:
3
- metadata.gz: db9520921cf6e3133db80395102de95622fde8c1
4
- data.tar.gz: 3627b3c4a37f71be5f9a3b6af00443efd5c4cdc2
2
+ SHA256:
3
+ metadata.gz: 4deaaab0070103b1803099e1067fd78dad5a34ac86dede4198c604a9d47bfc20
4
+ data.tar.gz: fbb4c771b4df864cd7460a9bf4c5fa2fb80a5c7b554dd7c1dda77cd5338e83f6
5
5
  SHA512:
6
- metadata.gz: 34d0d8a995420525d0faf38ebae7d7bcba6b96cd38ec2297ed35a5a1702ab3912184cfee15b61caa9db6ed5041f8bec1ea7e425c485d0a52b88f1d40b49b138a
7
- data.tar.gz: 43de1b4446acb27e2e99c0624a496e3c8b4efc7c65a3eda0342e8102351a6e1fe3876b966cc2d32c643bd804e62712de2a6562b05accc4e9c5dfafe40f1d6b37
6
+ metadata.gz: 7382cef361cd7b7aaf048a34695357e08bbd61c9c677a06fa130394ca2dbad2627dceb7c4ef2a7bd4bfe2d4b46723ba3edf47d083dc2dfab17d90778a416c35e
7
+ data.tar.gz: 2688032f252dcdda84464cbc6c09cb834942996fbc7c575c43f7ff73a7b8398ccb40631584c678b4c0ef207c10f2505a49f7cbd5277809d88efe9b00eb0c1156
@@ -16,6 +16,7 @@ There are some prerequisites to actually being able to run the unit/integration
16
16
  On macOS, edit your /etc/hosts and add the following line:
17
17
 
18
18
  127.0.0.1 posttest.localhost
19
+ 127.0.0.1 v2.bucket.localhost
19
20
 
20
21
  Then ensure that the following packages are installed (boto, s3cmd):
21
22
 
data/README.md CHANGED
@@ -17,9 +17,9 @@ Many commands are supported, including put, get, list, copy, and make bucket.
17
17
 
18
18
  ## Running
19
19
 
20
- To run the server, you just specify a root and a port.
20
+ To run the server, you must specify a root, a port, and your license key.
21
21
 
22
- fakes3 -r /mnt/fakes3_root -p 4567
22
+ fakes3 -r /mnt/fakes3_root -p 4567 --license YOUR_LICENSE_KEY
23
23
 
24
24
  ## Licensing
25
25
 
@@ -29,6 +29,8 @@ https://supso.org/projects/fake-s3
29
29
 
30
30
  Depending on your company's size, the license may be free. It is also free for individuals.
31
31
 
32
+ You pass the license key to Fake S3 with the command line option --license YOUR_LICENSE_KEY.
33
+
32
34
  ## Connecting to Fake S3
33
35
 
34
36
  Take a look at the test cases to see client example usage. For now, Fake S3 is
data/Rakefile CHANGED
@@ -16,7 +16,7 @@ end
16
16
 
17
17
  desc "Run the test_server"
18
18
  task :test_server do |t|
19
- system("bundle exec bin/fakes3 --port 10453 --root test_root")
19
+ system("bundle exec bin/fakes3 --port 10453 --license test --root test_root --corspostputallowheaders 'Authorization, Content-Length, Cache-Control'")
20
20
  end
21
21
 
22
22
  task :default => :test
@@ -15,8 +15,33 @@ module FakeS3
15
15
  method_option :limit, :aliases => '-l', :type => :string, :desc => 'Rate limit for serving (ie. 50K, 1.0M)'
16
16
  method_option :sslcert, :type => :string, :desc => 'Path to SSL certificate'
17
17
  method_option :sslkey, :type => :string, :desc => 'Path to SSL certificate key'
18
+ method_option :corsorigin, :type => :string, :desc => 'Access-Control-Allow-Origin header return value'
19
+ method_option :corsmethods, :type => :string, :desc => 'Access-Control-Allow-Methods header return value'
20
+ method_option :corspreflightallowheaders, :type => :string, :desc => 'Access-Control-Allow-Headers header return value for preflight OPTIONS requests'
21
+ method_option :corspostputallowheaders, :type => :string, :desc => 'Access-Control-Allow-Headers header return value for POST and PUT requests'
22
+ method_option :corsexposeheaders, :type => :string, :desc => 'Access-Control-Expose-Headers header return value'
23
+ method_option :license, :type => :string, :desc => 'Your license key, available at https://supso.org/projects/fake-s3'
18
24
 
19
25
  def server
26
+ license_key = options[:license]
27
+ if license_key.nil?
28
+ license_message = """
29
+ ======================
30
+ As of version 1.3, Fake S3 requires a license key passed with --license YOUR_LICENSE_KEY.
31
+ Please fix this before September 18, 2018.
32
+ You can get a license at:
33
+ https://supso.org/projects/fake-s3
34
+ ======================
35
+
36
+ """
37
+ licensing_required = Time.now > Time.utc(2018, 9, 19)
38
+ if licensing_required
39
+ abort license_message
40
+ else
41
+ warn license_message
42
+ end
43
+ end
44
+
20
45
  store = nil
21
46
  if options[:root]
22
47
  root = File.expand_path(options[:root])
@@ -45,6 +70,13 @@ module FakeS3
45
70
  end
46
71
  end
47
72
 
73
+ cors_options = {}
74
+ cors_options['allow_origin'] = options[:corsorigin] if options[:corsorigin]
75
+ cors_options['allow_methods'] = options[:corsmethods] if options[:corsmethods]
76
+ cors_options['preflight_allow_headers'] = options[:corspreflightallowheaders] if options[:corspreflightallowheaders]
77
+ cors_options['post_put_allow_headers'] = options[:corspostputallowheaders] if options[:corspostputallowheaders]
78
+ cors_options['expose_headers'] = options[:corsexposeheaders] if options[:corsexposeheaders]
79
+
48
80
  address = options[:address]
49
81
  ssl_cert_path = options[:sslcert]
50
82
  ssl_key_path = options[:sslkey]
@@ -53,8 +85,8 @@ module FakeS3
53
85
  abort "If you specify an SSL certificate you must also specify an SSL certificate key"
54
86
  end
55
87
 
56
- puts "Loading FakeS3 with #{root} on port #{options[:port]} with hostname #{hostname}" unless options[:quiet]
57
- server = FakeS3::Server.new(address,options[:port],store,hostname,ssl_cert_path,ssl_key_path, quiet: !!options[:quiet])
88
+ puts "Loading Fake S3 with #{root} on port #{options[:port]} with hostname #{hostname}" unless options[:quiet]
89
+ server = FakeS3::Server.new(address,options[:port],store,hostname,ssl_cert_path,ssl_key_path, quiet: !!options[:quiet], cors_options: cors_options)
58
90
  server.serve
59
91
  end
60
92
 
@@ -49,12 +49,19 @@ module FakeS3
49
49
  end
50
50
 
51
51
  class Servlet < WEBrick::HTTPServlet::AbstractServlet
52
- def initialize(server,store,hostname)
52
+ def initialize(server,store,hostname,cors_options)
53
53
  super(server)
54
54
  @store = store
55
55
  @hostname = hostname
56
56
  @port = server.config[:Port]
57
57
  @root_hostnames = [hostname,'localhost','s3.amazonaws.com','s3.localhost']
58
+
59
+ # Here lies hard-coded defaults for CORS Configuration
60
+ @cors_allow_origin = (cors_options['allow_origin'] or '*')
61
+ @cors_allow_methods = (cors_options['allow_methods'] or 'PUT, POST, HEAD, GET, OPTIONS')
62
+ @cors_preflight_allow_headers = (cors_options['preflight_allow_headers'] or 'Accept, Content-Type, Authorization, Content-Length, ETag, X-CSRF-Token, Content-Disposition')
63
+ @cors_post_put_allow_headers = (cors_options['post_put_allow_headers'] or 'Authorization, Content-Length')
64
+ @cors_expose_headers = (cors_options['expose_headers'] or 'ETag')
58
65
  end
59
66
 
60
67
  def validate_request(request)
@@ -101,7 +108,7 @@ module FakeS3
101
108
  response.status = 404
102
109
  response.body = XmlAdapter.error_no_such_key(s_req.object)
103
110
  response['Content-Type'] = "application/xml"
104
- response['Access-Control-Allow-Origin'] = '*'
111
+ response['Access-Control-Allow-Origin'] = @cors_allow_origin
105
112
  return
106
113
  end
107
114
 
@@ -134,7 +141,7 @@ module FakeS3
134
141
  response.header['ETag'] = "\"#{real_obj.md5}\""
135
142
  response['Accept-Ranges'] = "bytes"
136
143
  response['Last-Ranges'] = "bytes"
137
- response['Access-Control-Allow-Origin'] = '*'
144
+ response['Access-Control-Allow-Origin'] = @cors_allow_origin
138
145
 
139
146
  real_obj.custom_metadata.each do |header, value|
140
147
  response.header['x-amz-meta-' + header] = value
@@ -188,7 +195,7 @@ module FakeS3
188
195
  response.status = 200
189
196
  response.body = ""
190
197
  response['Content-Type'] = "text/xml"
191
- response['Access-Control-Allow-Origin'] = '*'
198
+ response['Access-Control-Allow-Origin'] = @cors_allow_origin
192
199
 
193
200
  case s_req.type
194
201
  when Request::COPY
@@ -240,9 +247,9 @@ module FakeS3
240
247
  response.header['ETag'] = "\"#{real_obj.md5}\""
241
248
  end
242
249
 
243
- response['Access-Control-Allow-Origin'] = '*'
244
- response['Access-Control-Allow-Headers'] = 'Authorization, Content-Length'
245
- response['Access-Control-Expose-Headers'] = 'ETag'
250
+ response['Access-Control-Allow-Origin'] = @cors_allow_origin
251
+ response['Access-Control-Allow-Headers'] = @cors_post_put_allow_headers
252
+ response['Access-Control-Expose-Headers'] = @cors_expose_headers
246
253
 
247
254
  response.status = 200
248
255
  end
@@ -322,9 +329,9 @@ module FakeS3
322
329
  end
323
330
 
324
331
  response['Content-Type'] = 'text/xml'
325
- response['Access-Control-Allow-Origin'] = '*'
326
- response['Access-Control-Allow-Headers'] = 'Authorization, Content-Length'
327
- response['Access-Control-Expose-Headers'] = 'ETag'
332
+ response['Access-Control-Allow-Origin'] = @cors_allow_origin
333
+ response['Access-Control-Allow-Headers'] = @cors_post_put_allow_headers
334
+ response['Access-Control-Expose-Headers'] = @cors_expose_headers
328
335
  end
329
336
 
330
337
  def do_DELETE(request, response)
@@ -348,10 +355,10 @@ module FakeS3
348
355
 
349
356
  def do_OPTIONS(request, response)
350
357
  super
351
- response['Access-Control-Allow-Origin'] = '*'
352
- response['Access-Control-Allow-Methods'] = 'PUT, POST, HEAD, GET, OPTIONS'
353
- response['Access-Control-Allow-Headers'] = 'Accept, Content-Type, Authorization, Content-Length, ETag, X-CSRF-Token, Content-Disposition'
354
- response['Access-Control-Expose-Headers'] = 'ETag'
358
+ response['Access-Control-Allow-Origin'] = @cors_allow_origin
359
+ response['Access-Control-Allow-Methods'] = @cors_allow_methods
360
+ response['Access-Control-Allow-Headers'] = @cors_preflight_allow_headers
361
+ response['Access-Control-Expose-Headers'] = @cors_expose_headers
355
362
  end
356
363
 
357
364
  private
@@ -371,9 +378,13 @@ module FakeS3
371
378
  end
372
379
 
373
380
  if elems.size == 0
374
- s_req.type = Request::DELETE_OBJECTS
375
- s_req.query = query
376
- s_req.webrick_request = webrick_req
381
+ if s_req.is_path_style
382
+ s_req.type = Request::DELETE_OBJECTS
383
+ s_req.query = query
384
+ s_req.webrick_request = webrick_req
385
+ else
386
+ s_req.type = Request::DELETE_BUCKET
387
+ end
377
388
  elsif elems.size == 1
378
389
  s_req.type = webrick_req.query_string == 'delete' ? Request::DELETE_OBJECTS : Request::DELETE_BUCKET
379
390
  s_req.query = query
@@ -486,8 +497,9 @@ module FakeS3
486
497
  s_req.path = webrick_req.path
487
498
  s_req.is_path_style = true
488
499
 
489
- if !@root_hostnames.include?(host) && !(IPAddr.new(host) rescue nil)
490
- s_req.bucket = host.split(".")[0]
500
+ root_hostname = @root_hostnames.find { |hostname| host.end_with?(".#{hostname}") }
501
+ if root_hostname
502
+ s_req.bucket = host[0...-root_hostname.size - 1]
491
503
  s_req.is_path_style = false
492
504
  end
493
505
 
@@ -550,6 +562,7 @@ module FakeS3
550
562
  @hostname = hostname
551
563
  @ssl_cert_path = ssl_cert_path
552
564
  @ssl_key_path = ssl_key_path
565
+ @cors_options = extra_options[:cors_options] or {}
553
566
  webrick_config = {
554
567
  :BindAddress => @address,
555
568
  :Port => @port
@@ -575,7 +588,7 @@ module FakeS3
575
588
  end
576
589
 
577
590
  def serve
578
- @server.mount "/", Servlet, @store, @hostname
591
+ @server.mount "/", Servlet, @store, @hostname, @cors_options
579
592
  shutdown = proc { @server.shutdown }
580
593
  trap "INT", &shutdown
581
594
  trap "TERM", &shutdown
@@ -1,3 +1,3 @@
1
1
  module FakeS3
2
- VERSION = "1.2.1"
2
+ VERSION = "1.3.0"
3
3
  end
@@ -17,7 +17,7 @@ class AwsSdkV2CommandsTest < Test::Unit::TestCase
17
17
  assert_not_nil bucket
18
18
 
19
19
  bucket_names = @resource.buckets.map(&:name)
20
- assert(bucket_names.index("v2_create_bucket") >= 0)
20
+ assert_not_nil bucket_names.index("v2_create_bucket")
21
21
  end
22
22
 
23
23
  def test_destroy_bucket
@@ -37,6 +37,14 @@ class AwsSdkV2CommandsTest < Test::Unit::TestCase
37
37
  assert_equal 'test', object.get.body.string
38
38
  end
39
39
 
40
+ def test_bucket_with_dots
41
+ bucket = @resource.create_bucket(bucket: 'v2.bucket')
42
+ object = bucket.object('key')
43
+ object.put(body: 'test')
44
+
45
+ assert_equal 'test', object.get.body.string
46
+ end
47
+
40
48
  def test_delete_object
41
49
  object = @bucket.object('exists')
42
50
  object.put(body: 'test')
@@ -10,7 +10,7 @@ class CLITest < Test::Unit::TestCase
10
10
  end
11
11
 
12
12
  def test_quiet_mode
13
- script = FakeS3::CLI.new([], :root => '.', :port => 4567, :quiet => true)
13
+ script = FakeS3::CLI.new([], :root => '.', :port => 4567, :license => 'test', :quiet => true)
14
14
  assert_output('') do
15
15
  script.invoke(:server)
16
16
  end
@@ -29,6 +29,8 @@ class PostTest < Test::Unit::TestCase
29
29
  ) { |response|
30
30
  assert_equal(response.code, 303)
31
31
  assert_equal(response.headers[:location], 'http://somewhere.else.com/?foo=bar&bucket=posttest&key=uploads%2F12345%2Fpost_test.rb')
32
+ # Tests that CORS Headers can be set from command line
33
+ assert_equal(response.headers[:access_control_allow_headers], 'Authorization, Content-Length, Cache-Control')
32
34
  }
33
35
  end
34
36
 
@@ -40,6 +42,8 @@ class PostTest < Test::Unit::TestCase
40
42
  'file'=>File.new(__FILE__,"rb")
41
43
  ) { |response|
42
44
  assert_equal(response.code, 200)
45
+ # Tests that CORS Headers can be set from command line
46
+ assert_equal(response.headers[:access_control_allow_headers], 'Authorization, Content-Length, Cache-Control')
43
47
  }
44
48
  end
45
49
 
@@ -52,6 +56,8 @@ class PostTest < Test::Unit::TestCase
52
56
  ) { |response|
53
57
  assert_equal(response.code, 201)
54
58
  assert_match(%r{^\<\?xml.*uploads/12345/post_test\.rb}m, response.body)
59
+ # Tests that CORS Headers can be set from command line
60
+ assert_equal(response.headers[:access_control_allow_headers], 'Authorization, Content-Length, Cache-Control')
55
61
  }
56
62
  end
57
63
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fakes3
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Curtis Spencer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-18 00:00:00.000000000 Z
11
+ date: 2018-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -249,7 +249,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
249
  version: '0'
250
250
  requirements: []
251
251
  rubyforge_project:
252
- rubygems_version: 2.6.13
252
+ rubygems_version: 2.7.7
253
253
  signing_key:
254
254
  specification_version: 4
255
255
  summary: Fake S3 is a server that simulates Amazon S3 commands so you can test your