I am having trouble forcing S3 to set CORS headers on all of the objects it returns from a bucket, though CORS is enabled, as client-side S3 uploads is working, the returned
TLDR; Make sure that every image or video element that requests a resource which (somewhere) needs CORS uses crossorigin="anonymous"
I ran into this issue for a video element that was exporting to a canvas. The CORS was setup in S3 correctly, but it still gave me an error and refused to play the video.
It turned out there was a second video element pointing to the same resource, and that video element didn't have crossorigin="anonymous"
. Hence, the second video played fine since it wasn't expecting an access-control
header, but the server response was cached and blocked the first video from playing because the cached server response didn't have an access-control header
Chrome has this amazing bug which they won't fix:
If you're lucky enough to have control over the code that is generating the tag you can add crossorigin="anonymous"
to the tag.
Like <img src="foo.bar/baz.jpg" crossorigin="anonymous" />
If you can modify either the URL for the tag or the URL for the XHR request, you could add a query parameter to one of them to bypass the cache.
Like foo.bar/baz.jpg?x-request=xhr
.
Safari has this issue too btw.
First of all, make sure an Origin
header with every request. If no Origin
header is sent, S3 won't send access-control
headers, as S3 deems them irrelevant (and typically, they are). A browser (for which the CORS mechanism is meant) will automatically send an Origin
header when doing cross-origin HTTP requests through XMLHTTPRequest.
In case of loading images with img
, you need to add crossorigin="anonymous"
attribute. See
MDN Documentation on crossorigin attribute. This will cause the browser to send an Origin
request header like it does with XMLHTTPRequest.
Going by the answer of Sam Selikoff, you may need to change
<AllowedOrigin>http://*</AllowedOrigin>
to
<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>
I haven't tested this.
Going by Paul Draper's comment on this answer: Watch out for caching issues. A browser may use a cached response that did not include the appropriate Access-Control
response headers. During development, you can clear your cache. In production, you must switch to a new URL for the resource, if it was used in a static manner before.
I also ran into this with an <image>
tag, and after following Myrne Stol's answer I added the crossorigin=anonymous
tag to my image tag. I verified that the Origin
header was indeed being sent to S3, but still, the Access-Control-Allow-Origin
header was not being sent in response.
I came across this SO answer and it solved it. I changed the AllowedOrigin
in my S3 config to this:
<AllowedOrigin>http://*</AllowedOrigin>
<AllowedOrigin>https://*</AllowedOrigin>
and now S3 responds with the access headers. Yay!