Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
Add ability to control CORS Headers (resolves #130)
Browse files Browse the repository at this point in the history
The issue only required modifying the Allowed-Headers,
but it seemed strange to add the ability to control
that one without being able to control the others

- Current behavior without added flags is unnaffected
- No existing assertions are changed
- Added assertions to demonstrate control of CORS Headers
  • Loading branch information
ushatil authored and jubos committed Jan 25, 2018
1 parent 67f8941 commit 994f7ff
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ end

desc "Run the test_server"
task :test_server do |t|
system("bundle exec bin/fakes3 --port 10453 --root test_root")
system("bundle exec bin/fakes3 --port 10453 --root test_root --corspostputallowheaders 'Authorization, Content-Length, Cache-Control'")
end

task :default => :test
14 changes: 13 additions & 1 deletion lib/fakes3/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ class CLI < Thor
method_option :limit, :aliases => '-l', :type => :string, :desc => 'Rate limit for serving (ie. 50K, 1.0M)'
method_option :sslcert, :type => :string, :desc => 'Path to SSL certificate'
method_option :sslkey, :type => :string, :desc => 'Path to SSL certificate key'
method_option :corsorigin, :type => :string, :desc => 'Access-Control-Allow-Origin header return value'
method_option :corsmethods, :type => :string, :desc => 'Access-Control-Allow-Methods header return value'
method_option :corspreflightallowheaders, :type => :string, :desc => 'Access-Control-Allow-Headers header return value for preflight OPTIONS requests'
method_option :corspostputallowheaders, :type => :string, :desc => 'Access-Control-Allow-Headers header return value for POST and PUT requests'
method_option :corsexposeheaders, :type => :string, :desc => 'Access-Control-Expose-Headers header return value'

def server
store = nil
Expand Down Expand Up @@ -45,6 +50,13 @@ def server
end
end

cors_options = {}
cors_options['allow_origin'] = options[:corsorigin] if options[:corsorigin]
cors_options['allow_methods'] = options[:corsmethods] if options[:corsmethods]
cors_options['preflight_allow_headers'] = options[:corspreflightallowheaders] if options[:corspreflightallowheaders]
cors_options['post_put_allow_headers'] = options[:corspostputallowheaders] if options[:corspostputallowheaders]
cors_options['expose_headers'] = options[:corsexposeheaders] if options[:corsexposeheaders]

address = options[:address]
ssl_cert_path = options[:sslcert]
ssl_key_path = options[:sslkey]
Expand All @@ -54,7 +66,7 @@ def server
end

puts "Loading FakeS3 with #{root} on port #{options[:port]} with hostname #{hostname}" unless options[:quiet]
server = FakeS3::Server.new(address,options[:port],store,hostname,ssl_cert_path,ssl_key_path, quiet: !!options[:quiet])
server = FakeS3::Server.new(address,options[:port],store,hostname,ssl_cert_path,ssl_key_path, quiet: !!options[:quiet], cors_options: cors_options)
server.serve
end

Expand Down
38 changes: 23 additions & 15 deletions lib/fakes3/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,19 @@ def inspect
end

class Servlet < WEBrick::HTTPServlet::AbstractServlet
def initialize(server,store,hostname)
def initialize(server,store,hostname,cors_options)
super(server)
@store = store
@hostname = hostname
@port = server.config[:Port]
@root_hostnames = [hostname,'localhost','s3.amazonaws.com','s3.localhost']

# Here lies hard-coded defaults for CORS Configuration
@cors_allow_origin = (cors_options['allow_origin'] or '*')
@cors_allow_methods = (cors_options['allow_methods'] or 'PUT, POST, HEAD, GET, OPTIONS')
@cors_preflight_allow_headers = (cors_options['preflight_allow_headers'] or 'Accept, Content-Type, Authorization, Content-Length, ETag, X-CSRF-Token, Content-Disposition')
@cors_post_put_allow_headers = (cors_options['post_put_allow_headers'] or 'Authorization, Content-Length')
@cors_expose_headers = (cors_options['expose_headers'] or 'ETag')
end

def validate_request(request)
Expand Down Expand Up @@ -101,7 +108,7 @@ def do_GET(request, response)
response.status = 404
response.body = XmlAdapter.error_no_such_key(s_req.object)
response['Content-Type'] = "application/xml"
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Origin'] = @cors_allow_origin
return
end

Expand Down Expand Up @@ -134,7 +141,7 @@ def do_GET(request, response)
response.header['ETag'] = "\"#{real_obj.md5}\""
response['Accept-Ranges'] = "bytes"
response['Last-Ranges'] = "bytes"
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Origin'] = @cors_allow_origin

real_obj.custom_metadata.each do |header, value|
response.header['x-amz-meta-' + header] = value
Expand Down Expand Up @@ -188,7 +195,7 @@ def do_PUT(request, response)
response.status = 200
response.body = ""
response['Content-Type'] = "text/xml"
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Origin'] = @cors_allow_origin

case s_req.type
when Request::COPY
Expand Down Expand Up @@ -240,9 +247,9 @@ def do_multipartPUT(request, response)
response.header['ETag'] = "\"#{real_obj.md5}\""
end

response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Headers'] = 'Authorization, Content-Length'
response['Access-Control-Expose-Headers'] = 'ETag'
response['Access-Control-Allow-Origin'] = @cors_allow_origin
response['Access-Control-Allow-Headers'] = @cors_post_put_allow_headers
response['Access-Control-Expose-Headers'] = @cors_expose_headers

response.status = 200
end
Expand Down Expand Up @@ -322,9 +329,9 @@ def do_POST(request,response)
end

response['Content-Type'] = 'text/xml'
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Headers'] = 'Authorization, Content-Length'
response['Access-Control-Expose-Headers'] = 'ETag'
response['Access-Control-Allow-Origin'] = @cors_allow_origin
response['Access-Control-Allow-Headers'] = @cors_post_put_allow_headers
response['Access-Control-Expose-Headers'] = @cors_expose_headers
end

def do_DELETE(request, response)
Expand All @@ -348,10 +355,10 @@ def do_DELETE(request, response)

def do_OPTIONS(request, response)
super
response['Access-Control-Allow-Origin'] = '*'
response['Access-Control-Allow-Methods'] = 'PUT, POST, HEAD, GET, OPTIONS'
response['Access-Control-Allow-Headers'] = 'Accept, Content-Type, Authorization, Content-Length, ETag, X-CSRF-Token, Content-Disposition'
response['Access-Control-Expose-Headers'] = 'ETag'
response['Access-Control-Allow-Origin'] = @cors_allow_origin
response['Access-Control-Allow-Methods'] = @cors_allow_methods
response['Access-Control-Allow-Headers'] = @cors_preflight_allow_headers
response['Access-Control-Expose-Headers'] = @cors_expose_headers
end

private
Expand Down Expand Up @@ -550,6 +557,7 @@ def initialize(address, port, store, hostname, ssl_cert_path, ssl_key_path, extr
@hostname = hostname
@ssl_cert_path = ssl_cert_path
@ssl_key_path = ssl_key_path
@cors_options = extra_options[:cors_options] or {}
webrick_config = {
:BindAddress => @address,
:Port => @port
Expand All @@ -575,7 +583,7 @@ def initialize(address, port, store, hostname, ssl_cert_path, ssl_key_path, extr
end

def serve
@server.mount "/", Servlet, @store, @hostname
@server.mount "/", Servlet, @store, @hostname, @cors_options
shutdown = proc { @server.shutdown }
trap "INT", &shutdown
trap "TERM", &shutdown
Expand Down
6 changes: 6 additions & 0 deletions test/post_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def test_redirect
) { |response|
assert_equal(response.code, 303)
assert_equal(response.headers[:location], 'http://somewhere.else.com/?foo=bar&bucket=posttest&key=uploads%2F12345%2Fpost_test.rb')
# Tests that CORS Headers can be set from command line
assert_equal(response.headers[:access_control_allow_headers], 'Authorization, Content-Length, Cache-Control')
}
end

Expand All @@ -40,6 +42,8 @@ def test_status_200
'file'=>File.new(__FILE__,"rb")
) { |response|
assert_equal(response.code, 200)
# Tests that CORS Headers can be set from command line
assert_equal(response.headers[:access_control_allow_headers], 'Authorization, Content-Length, Cache-Control')
}
end

Expand All @@ -52,6 +56,8 @@ def test_status_201
) { |response|
assert_equal(response.code, 201)
assert_match(%r{^\<\?xml.*uploads/12345/post_test\.rb}m, response.body)
# Tests that CORS Headers can be set from command line
assert_equal(response.headers[:access_control_allow_headers], 'Authorization, Content-Length, Cache-Control')
}
end

Expand Down

0 comments on commit 994f7ff

Please sign in to comment.