尝试使用 Axios 向 API 发送 POST 请求时,响应中的“Access-Control-Allow-Credentials”标头为“ ”

IT技术 node.js reactjs cors axios jsreport
2021-05-18 12:55:00

我有一个在 localhost:3000 上运行的 react 应用程序和一个在 localhost:8000 上运行的 nodeJS-express 服务器,我需要向 jsreport API 发送一个 POST 请求,但是当我尝试发送请求时,我收到以下错误:

从源“ http://localhost:3000访问 XMLHttpRequest at ' http://localhost:5488/api/report '已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:的值响应中的“Access-Control-Allow-Credentials”标头为“”,当请求的凭据模式为“包含”时,该标头必须为“真”。XMLHttpRequest 发起的请求的凭证模式由 withCredentials 属性控制。

发布请求:

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'
})

服务器.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);
})

如果我在 axios 中使用 .withCredentials 并在服务器中建立标头和 cors 配置,我不明白为什么凭据为空。

4个回答

我使用了下一个代码而不是 axios 请求,它起作用了:

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

将凭据设置为“同源”解决了这个问题,但是当我想使用 jsreport 时,我找到了一个包,可以在不使用 fetch 或 axios 的情况下使这更容易。

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

使用 jsreport 方法,我可以在 react 组件中显示我的报告

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

更新 Server.js 如下

var corsOptions = {
  origin: 'http://localhost:3000',
  credentials : true
 }

app.use(cors(corsOptions));

app.use(function (req, res, next) {	
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');    
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');    
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');   
    res.setHeader('Access-Control-Allow-Credentials', true);    
    next();
});

我一直在摆弄持久的用户会话一段时间,并且在将passport / passport-local(用于身份验证)mongoose, express-session、 和connect-mongo(用于在 mongo 中存储会话串在一起时遇到了麻烦

@mshibl 评论帮助我更进一步,并corsexpress最终cookies正确传递了这些选项希望这可以帮助其他有类似问题的人

app.use(cors({
  credentials: true,
  origin: "http://localhost:3000"
}));

这对我有用

export default function({ $axios, redirect }, inject) {
  // Base URL
  const base = process.env.API_URL

  // Sett withCredentials on $axios before creating instance
  $axios.defaults.withCredentials = true

  // Create a custom axios instance
  const api = $axios.create({
    baseURL: base,
    responseType: 'json',
    timeout: 10000,
    // withCredentials: true,
    headers: {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json'
    }
  })

  // Inject to context as $api
  inject('api', api)

在创建我自己的实例之前设置 defaults.withCredentials 为我解决了这个问题。