1

I'm using Angular for my frontend, and Express for backend. I ran into a CORS problem with one of several api endpoints which are similarly configured:

Failed to load http://localhost:3000/api/deletePost: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 400.

Any help would be appreciated. Thank you.

Front-end code (web-calls.service.ts):

// Not working

deleteArticle(articleId:string): Observable<any> {
  return this.http.post('http://localhost:3000/api/deletePost', JSON.stringify(articleId), {
    headers: new HttpHeaders().set('Content-Type', 'application/json'),
  }).map(data => {
    if (data["status"] == 200) {
      this.router.navigate(['posts']);
    } else if (data["status"] == 500) {
      // TODO: error message and handling here
      console.log(data);
    }
    return data["status"];
  });
}


// working

createOrUpdatePost(url, articleComplete): Observable<number> {
  return this.http.post('http://localhost:3000/api/updatePost', JSON.stringify(articleComplete), {
    headers: new HttpHeaders().set('Content-Type', 'application/json'),
  }).map(data => {
    if (data["status"] == 200) {
      this.router.navigate(['post' + '/' + data["response"]]);
    } else if (data["status"] == 500) {
      // TODO: error message and handling here
      console.log(data);
    }
    return data["status"];
  });
}

Backend code (app.js):

app.all('/*', function(req, res, next) {
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'authorization,Content-Type, X-Requested-With');
    res.header('Access-Control-Allow-Origin', '*');
    next();
});

app.use('/api', api);

Also tried this configuration for app.js:

function setupCORS(req, res, next) {
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'authorization,Content-Type');
    res.header('Access-Control-Allow-Origin', '*');
    console.log("METHOD: " + req.method);
    if (req.method === 'OPTIONS') {
        console.log('OPTIONS >>>');
        res.status(200).end();
    } else {
        console.log('NOT OPTIONS >>>');
        next();
    }
}
app.all('/*', setupCORS);

Backend code (api.js):

router.post('/deletePost', function (req, res, next) {
    console.log('here here'); // does not print to console
    // other code here
}

router.post('/updatePost', function (req, res, next) {
    console.log('here here'); // prints just fine
    // other code here
}
Edwin Chua
  • 658
  • 1
  • 8
  • 20

3 Answers3

0

once I had a similar problem and I remember solving it by adding this header: Access-Control-Allow-Credentials: true maybe that helps you.

And BTW I recommend you to not use JSON.stringify() before sending the data.

Update

You can also use curl to debug CORS as says in this questionHow can you debug a CORS request with cURL?

Iván E. Sánchez
  • 1,183
  • 15
  • 28
  • would you be able to elaborate of why not to use `JSON.stringify()` please? Is it a best practice? Was it because my data type was string? – Edwin Chua Jan 03 '18 at 03:06
0

So apparently, JSON.stringify('string') does not mean that the data type is correctly sent as a json string.

Instead, using JSON.stringify(object) works.

Lesson learnt: The CORS error displayed on the browser console is not helpful if your data is not correctly formatted.

What is should be:

// changed the method to accept an Article object instead of a string.

deleteArticle(article:Article): Observable<any> {
  return this.http.post('http://localhost:3000/api/deletePost', JSON.stringify(article), {
    headers: new HttpHeaders().set('Content-Type', 'application/json'),
  }).map(data => {
    if (data["status"] == 200) {
      this.router.navigate(['posts']);
    } else if (data["status"] == 500) {
      // TODO: error message and handling here
      console.log(data);
    }
    return data["status"];
  });
}
Edwin Chua
  • 658
  • 1
  • 8
  • 20
0

you might want to use the proxy to mitigate CORS on your local server, this is a better way to handle CORS when you are developing locally.To set up a proxy on your angular app, create a new file proxy.config.json in your project folder alongside package.json and add these line into it:

{
 "/localapi/*": {
"target": "http://localhost:4646",
"pathRewrite": {
  "^/localapi": ""
},   
"changeOrigin": true,
"secure": false,
"logLevel": "debug"
  }
}

add your local api address e.g 'mydomain/api/' so that all the requests with this url will be sent through the proxy. Next modify your package.json and change the value of "start"

"start": "ng serve --proxy-config proxy.config.json"

now to start your app use the above command instead of ng serve and you wont face any CORS issue, no need to add custom headers to each request on your server manually.

Bilal Alam
  • 874
  • 10
  • 26