node.jsreactjscorsaxiosjsreport

'Access-Control-Allow-Credentials' header in the response is ' ' when trying to send a POST request to an API using Axios


I have a react app running in localhost:3000 and a nodeJS-express server on localhost:8000, I need to send a POST request to the jsreport API, but when I try to send the request I got the following error:

Access to XMLHttpRequest at 'http://localhost:5488/api/report' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Post request:

axios.defaults.withCredentials = true;

axios.post('http://localhost:5488/api/report',
{withCredentials: true, crossorigin: true},
{
  "template": {
    "content": "<h1>Hello {{foo}}</h1>",
    "engine": "handlebars",
    "recipe": "chrome-pdf"
  },
  "data": {
    "foo": "world"
  }
}).then((response)=> {
  fs.writeFileSync('/reports/report.pdf', response.content)
}).catch(function (error) {
  console.log('AXIOS error: '+ error);
  return 'errorReport'
})

Server.js:

var corsOptions = {
  origin: 'http://localhost:3000',
  credentials : true
 }
app.use(cors(corsOptions));
app.use((req, res, next) => {
  res.header('Access-Control-Expose-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  res.header("Access-Control-Allow-Origin", "http://localhost:3000");
  res.header("Access-Control-Allow-Credentials", true);
  res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  const err = new Error('Not Found');
  err.status = 404;
  next(err);
})

I don't understand why the credentials are empty If I use .withCredentials in axios and established the headers and the cors configuration in the server.


Solution

  • I used the next code instead of the axios request and it worked:

    fetch('http://localhost:5488/api/report', {
      method: 'POST',
      body: JSON.stringify(data),
      headers:{
        'Content-Type': 'application/json'
      },
      credentials: "same-origin",
    }
    

    Set credentials to "same-origin" fixed the problem, but as I wanted to use jsreport I found a package to make this easier without using fetch or axios.

    import jsreport from 'jsreport-browser-client-dist'
    jsreport.serverUrl = 'http://localhost:5488'
    jsreport.render(document.getElementById('reportPlaceholder'), data)
    

    Using the jsreport methods I could show my report in the react component

    <div id="reportPlaceholder">
          <p>there should be a report here...</p>
    </div>