Unable to fetch blogs because of cors policy

I created a ghost blog samson.ghost.io .

In my laptop, I am running a simple react app on localhost:9000, and I need to fetch blogs the ghost blog.

I have installed @tryghost/content-api via npm and I have the content API key
and I using the sample code as:

const api = new GhostContentAPI({
  url: 'https://samson.ghost.io',
  key: 'my-content-api-key',
  version: "v3"
});


api.posts
    .browse({limit: 5, include: 'tags,authors'})
    .then((posts) => {
        posts.forEach((post) => {
            console.log(post.title);
        });
    })
    .catch((err) => {
        console.error(err);
    });

But this is giving me the cors error:

Access to XMLHttpRequest at ā€¦urlā€¦ from origin 'http://localhost:9000 has been blocked by CORS policy, no ā€˜Access-Control-Allow-Originā€™ header is present on the requested resource.

I have tried the answers provided here:

but modifying webpack doesnā€™t change anything.

How do I solve this?

Anyone? I canā€™t get it to work

Hey there @_samayo. Cool to see you playing around with the Ghost Content API. Are you trying to use the API with a front-end React component? You might want to look into using something like Create React App (https://create-react-app.dev/) that comes bundled with a few things include how to avoid CORS issues:
Proxying API Requests in Development | Create React App

Iā€™d recommend this if youā€™re not super familiar with React, either that or you can look into tools like Axios to help you retrieve content from the Ghost API. Thereā€™s a pretty good tutorial here https://alligator.io/react/axios-react/

Hope this helps! :slightly_smiling_face:

@_samayo Iā€™m not sure whatā€™s happening here because Ghost definitely returns the correct access-control-allow-origin header for Content API requests so that any host is allowed to connect. Hereā€™s an example:

āžœ curl -H 'Origin: http://localhost:9000' -I https://demo.ghost.io/ghost/api/v3/content/posts/\?limit\=5\&include\=tags,authors\&token\=4fef5f91af9b42d01461e19b3c | grep access-control-allow-origin

access-control-allow-origin: *

Are you able to post a screenshot of the error message in your browser console?

Iā€™m getting the same error when developing locally and when deploying to a front end that requires some images from Ghost. Iā€™m running Ghost at content.example.com and have the front end deployed on example.com.

I tried the curl command you shared with my Ghost URL and API key. I got the same result:

access-control-allow-origin: *    

The error on Chrome reads:

Access to fetch at 'https://content.example.com/content/images/2019/10/example.jpeg' from origin 'https://example.com' has been blocked by CORS policy: 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.    

and on Safari:

Cannot load image https://content.example.com/content/images/2019/10/example.jpg due to access control checks.
Failed to load resource: Response served by service worker is opaque.

Would the best solution be to properly configure access-control-allow-origin?
How do you configure access-control-allow-origin?

I couldnā€™t find much on trusted domains in the Ghost docs, but some forum mentions here and here seem to suggest that is the solution. The accepted answer points to the API docs but I couldnā€™t find anything about CORS or trusted domains when searching there.

Thanks!

@eriknakamura the Content API itself has the required CORS heading to allow all origins. The trusted domains references are to the old+removed v0.1 Public API and are not relevant to the v2/v3 Content API.

In your case itā€™s not failing on the API but on fetching an image, the /content/images/* requests do not have any CORS headers. What is it you are doing with front-end code that requires fetching an image using JavaScript?

Ok thank you for clearing up the trusted domains situation. API endpoint != image url, got it.

Iā€™m creating a ā€œGraph Viewā€ of my blog posts using Cytoscapejs which uses the post thumbnails as a background image for each node.

Would using an image CDN (storage adapter) allow me to configure the CORS and fetch images however I want?

@eriknakamura you should be able to configure nginx (or whichever web server you have used) to add the access-control-allow-origin header to any /content/images/* requests.

1 Like

Thanks for the tip! You led me right to the solution. I added the access-control-allow-origin header to static file requests as follows:

  1. Navigate to the Ghost nginx config files with cd /var/www/ghost/system/files
  2. Open up example.com-ssl.conf (you can use nano example.com-ssl.conf
  3. Add this code inside the existing location / {}:
    if ($request_uri ~* ".(ico|css|js|gif|jpe?g|png)$") {
        add_header 'Access-Control-Allow-Origin' '[ORIGIN_URL_TO_ENABLE]';
        break;
    }

Replace [ORIGIN_URL_TO_ENABLE] with the origin URL that youā€™re trying to access the images from.

Your final config file should look something like this:

  1. Exit and save, then restart nginx with sudo systemctl restart nginx
  2. Test your new header using curl:
curl -I [IMAGE_URL]

You should see the access-control-allow-origin header print out along with the other headers like this:

HTTP/2 200 
server: nginx/1.10.3 (Ubuntu)
date: Wed, 11 Dec 2019 02:34:45 GMT
content-type: image/png
content-length: 176375
x-powered-by: Express
accept-ranges: bytes
access-control-allow-origin: https://example.com

The browser should now be happy to display the cross origin resource!

Hi! Iā€™ve started having similar problems with CORS.
Everything worked well for a while, but lately Iā€™ve noticed the CORS errorā€¦

The weird thing is, when I CURL my ghost.io-hosted API or use javascript Ghost Content API client, it returns no access-control-allow-origin headers, but when I get the api url in the browser, there is access-control-allow-origin *

Any hints, what can be wrong here, and what I can do to fix the issue?

Thanks in advance,
Kitty

I am late in the party but if you have CORS issue during local development, try to check your protocol.
You should query http://localhost:{port} on localhost not https://