Gatsby: Gastby CORS Issues

Created on 6 May 2019  路  7Comments  路  Source: gatsbyjs/gatsby

Hi -

I am a newbie to gatbsy and am running into CORS issues with my fetch request even after passing the headers required?

I am trying to create a download button for fiels (images) I have stored in google cloud storage. This is the function (replaced bucket name):

const downloadImage = () => {
      fetch('https://storage.googleapis.com/bucket/picture.jpg', {
        method: 'GET',
        headers:{
          'Access-Control-Allow-Origin': '*',
          'Content-Type': 'multipart/form-data'
        }}).then(response => {
                const filename =  'download.jpg';
                response.blob().then(blob => {
                  let url = window.URL.createObjectURL(blob);
                  let a = document.createElement('a');
                  a.href = url;
                  a.download = filename;
                  a.click();
                  a.remove();
        });
     });
  }

And this is the error I get:

Access to fetch at 'https://storage.googleapis.com/bucket/picture.jpg' from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I am passing in the headers in the request so not sure what else is required? Do I need to add the 'Access-Control-Allow-Origin': '*' somewhere in the build script (gastby-config)? Thanks for any help!

Most helpful comment

@btahir - Access-Control-Allow-Origin is a RESPONSE header, not a request header. In other words, if you made the following curl request, replacing https://www.example.com/ with the URL of your website, you would expect to see an Access-Control-Allow-Origin header returned from storage.googleapis.com if your cloud storage is properly configured for your domain as per the instructions that wardpeet linked above. If you don't see that header returned, then your cloud storage is not properly configured.

In the browser, you do not add the "Access-Control-Request-Headers" header shown in the below curl request. It is added by the browser automatically.

curl -v 'https://storage.googleapis.com/bucket/picture.jpg' -X OPTIONS -H 'Access-Control-Request-Method: GET' -H 'Origin: https://www.example.com' -H 'Referer: https://www.example.com/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36' -H 'Access-Control-Request-Headers: access-control-allow-origin' --compressed

For further info, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control

All 7 comments

@btahir sadly this is not related to gastby but to CORS itself. Please check https://cloud.google.com/storage/docs/cross-origin for more information

@wardpeet Thanks for replying. Its a CORS issue but its being caused because I cannot pass the correct header (in this case Access-Control-Allow-Origin) in my request. If I use the proxy feature in development, I seem to get around this: https://www.gatsbyjs.org/docs/api-proxy/

There must be a simple tweak here that I am missing to make this work in production...

To help us best begin debugging the underlying cause, it is incredibly helpful if you're able to create a minimal reproduction. This is a simplified example of the issue that makes it clear and obvious what the issue is and how we can begin to debug it.

Are you testing this on localhost or on a https domain?
You might want to add no-cors to the request and see what it does.

I have created a dummy test bucket in Google Cloud Storage that is Public (can be viewed by anyone). This is the fetch request to get the image stored there:

const downloadImage = () => {
      fetch('https://storage.googleapis.com/thistestbucket/star.jpg', {
        method: 'GET',
        headers:{
          'Access-Control-Allow-Origin': '*',
        }}).then(response => {
                console.log(response);
     });
  }

The error is the same as above.

You can trigger this in an onclick event in a Button:

<Button onClick={downloadImage}>Click Me</Button>

And no-cors will just return an opaque response aka empty image.

@btahir - Access-Control-Allow-Origin is a RESPONSE header, not a request header. In other words, if you made the following curl request, replacing https://www.example.com/ with the URL of your website, you would expect to see an Access-Control-Allow-Origin header returned from storage.googleapis.com if your cloud storage is properly configured for your domain as per the instructions that wardpeet linked above. If you don't see that header returned, then your cloud storage is not properly configured.

In the browser, you do not add the "Access-Control-Request-Headers" header shown in the below curl request. It is added by the browser automatically.

curl -v 'https://storage.googleapis.com/bucket/picture.jpg' -X OPTIONS -H 'Access-Control-Request-Method: GET' -H 'Origin: https://www.example.com' -H 'Referer: https://www.example.com/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36' -H 'Access-Control-Request-Headers: access-control-allow-origin' --compressed

For further info, see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control

Ah I see! Sorry didn't get that before. I was able to make it work by adjusting the Bucket Level CORS policies. Thanks! :)

For reference, you can use this link for instructions on how to set cors using gsutil: https://cloud.google.com/storage/docs/gsutil/commands/cors

Was this page helpful?
0 / 5 - 0 ratings