Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CORS, Amazon S3, and Rails - Fails on IE 10 and Safari

IE 10 supports CORS. Amazon S3 supports CORS.

We have direct-from-site-to-S3 uploading working in all browsers but IE 10 (not bothering with IE 9-). It works like this:

  1. User picks a file (drag and drop or pick from file input)

  2. (POST) We have to "sign" the request before it goes to S3 ($.post('/static/sign_asset', { ... }) which has a callback that fires perfectly all day long.

  3. (POST) We then make the XHR to S3 with the file data and the data from the signing and such.

 var xhr = new XMLHttpRequest(); // etc var fd = new FormData(); // etc xhr.open('POST', url, true); xhr.send(fd); 

The file uploads, everything works perfectly in all browsers except...

Problems start in IE 10:

  1. Origin null not found in Access-Control-Allow-Origin header. and XMLHttpRequest: Network Error 0x80070005, Access is denied. No other browsers are showing this after we have set response.headers["Access-Control-Allow-Origin"] = "*" in the controller that sends the response. Even when we had this wrong, Chrome would show this error, but the request would still go through.

  2. The file actually does get uploaded to S3, despite this error. Amazon S3 does it's 303 redirect thing - which is our verification that the file was successfully uploaded.

  3. (GET) This is a redirect on a CORS Ajax request, so the "redirect" doesn't refresh the page it just comes back and hits our servers. IE 10 makes this request with a Content-Type of multipart/form-data; boundary=---------------------------7dd2ce2201da

This is what causes Rails to bug out.

Started GET "/static/signed/asset/tsabat/83ee6840-7158-0130-c19b-28cfe912f6ff?bucket=s.cdpn.io&key=5%2Fauthor-tim_2.jpg&etag=%2260fb3876d516553ff6f3a018066b3250%22" for 127.0.0.1 at  2013-03-17 10:46:36 -0700  EOFError - bad content body:   (gem) rack-1.4.5/lib/rack/multipart/parser.rb:74:in `block in Rack::Multipart::Parser#fast_forward_to_first_boundary'  (gem) rack-1.4.5/lib/rack/multipart/parser.rb:72:in `Rack::Multipart::Parser#fast_forward_to_first_boundary'   (gem) rack-1.4.5/lib/rack/multipart/parser.rb:72:in `Rack::Multipart::Parser#parse'   (gem) rack-1.4.5/lib/rack/multipart/parser.rb:15:in `Rack::Multipart.parse_multipart'   (gem) rack-1.4.5/lib/rack/multipart.rb:25:in `ActionDispatch::Request#parse_multipart'   (gem) rack-1.4.5/lib/rack/request.rb:336:in `ActionDispatch::Request#POST'   (gem) rack-1.4.5/lib/rack/request.rb:201:in `ActionDispatch::Request#POST' 

Safari fails too (6.0.2)

Safari returns a 200 status code and Rails doesn't freak out about the redirect, but the xhr.status is wrong. xhr.readyState == 4, but xhr.status == 0. We were looking for 200 to make sure it worked OK. That is easy enough to fix, but still...

Chrome does fine - Doesn't appear to even set Content-Type

Firefox does fine - Content-Type application/json; charset=utf-8


There are example pages that show how well IE 10 handles CORS, but they don't deal with this redirect issue.

like image 610
Chris Coyier Avatar asked Mar 17 '13 20:03

Chris Coyier


People also ask

Why am I getting an access denied error message when I upload files to my Amazon S3 bucket?

If you're getting Access Denied errors on public read requests that are allowed, check the bucket's Amazon S3 Block Public Access settings. Review the S3 Block Public Access settings at both the account and bucket level. These settings can override permissions that allow public read access.


1 Answers

CodePen team member here. We figured this out...

We wanted to depend on the 303 redirect built into S3's POST functionality, but it proved to be problematic, as shown above. Instead we simply stopped using the S3 Form Field success_action_redirect and switched to success_action_status.

For posterity, don't depend on the S3's 303 redirect to work consistently across browsers for xhr requests. If you do, you'll spend your time fighting invalid headers, null origins, and dragons.

like image 111
timsabat Avatar answered Oct 19 '22 22:10

timsabat