Ilan lewin
Ilan lewin

Reputation: 1639

cors+s3+browser cache+chrome extension

Yes. this is a complex question. i will try to nake it brief.

My website fetches resources from s3. I also have an extension that needs to prefetch that s3 file when someone does a google query, so later when they go on my site ,the resource is cached. At this point I should probably stress that I'm not doing anything malicious. just a matter of user experience. My problem is. that making an ajax request to s3 fron the extension (either from content-script or background) doesn't send an origin header. This means that the resource is downloaded and cached without an allow origin header. s3 doesnt add that allow-origin:* if theres no origin in the request. so later, on my site it fails due to missing allow-origin header in cached file :-(

Any ideas on a better way to prefetch to browser cache?

Is there a way to force the ajax request to send an origin? Any origin? Since I have an allow-origin:* on my s3 bucket, I think any origin will do accept null. Thanks

Edit: Ended up using one of Rob W's solutions. You are awesome. Let me comment on each of the options he suggested:

  1. Not to add the host premissions on my manifest - clever idea but wouldn't work for me since I have a content script which runs on any website, so I must use a catch-all wildcard, and I don't think there is an "exclude" permission option.

  2. I tried it, it issues a null origin, which as expected ends up in S3 sending the allow-origin:* header as required. this means I don't get that "allow-origin header missing" error, however the file is then not served from cache. I guess for it to be actually served from cache in chrome this has to be exactly the same origin. so that was very close but not enough.

  3. third option is a charm. And it is the simplest. I didn't know I was able to manipulate the origin header. So I do that and set the exact origin of my website - And it works. The file is cached and later served from cache. I must stress that i had to add a Url filter to only apply this to requests going out to my s3 bucket, otherwise I expect this would wreak havoc on the user's browser.

Thanks. Well done

Upvotes: 0

Views: 1256

Answers (1)

Rob W
Rob W

Reputation: 349192

You've got three options:

  1. Do not add the host permission for S3 to your manifest file. Then the extension will not have the blanket permission to access the resource, and an Origin request header will be sent with the request.
  2. Use a non-extension frame to perform the AJAX request. For example, the following method will result in a cross-origin GET request with Origin: null.

    function prefetchWithOrigin(url) {
        var html = '<script>(' + function(url) {
            var x = new XMLHttpRequest();
            x.open('GET', url);
            x.onloadend = function() {
                parent.postMessage('done', '*');
            };
            x.send();
        } + ')(' + JSON.stringify(url) + ');</script>';
        var f = document.createElement('iframe');
        f.src = 'data:text/html,' + encodeURIComponent(html);
        (document.body || document.documentElement).appendChild(f);
        window.addEventListener('message', function listener(event) {
            // Remove frame upon completion
            if (event.source === f.contentWindow) {
                window.removeEventListener('message', listener);
                f.remove();
            }
        });
    }
    
  3. Use the chrome.webRequest.onBeforeSendHeaders event to manually append the Origin header.

Upvotes: 1

Related Questions