fakes3 1.2.1 → 1.3.0

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
- 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