“请求的资源上不存在‘Access-Control-Allow-Origin’标头” POST 请求成功后引发错误

Posted

技术标签:

【中文标题】“请求的资源上不存在‘Access-Control-Allow-Origin’标头” POST 请求成功后引发错误【英文标题】:"No 'Access-Control-Allow-Origin' header is present on the requested resource" error thrown after successful POST request 【发布时间】:2019-08-17 10:16:40 【问题描述】:

我正在尝试设置一个 API 来接收 CORS POST 请求,并且我已经达到了成功发布数据的地步,但是我收到错误消息“CORS 策略已阻止访问 XMLHttpRequest:否请求的资源上存在“Access-Control-Allow-Origin”标头。”这导致 AJAX 调用返回错误状态而不是成功状态。

这是客户端的 AJAX 调用:

$.ajax(
  type: 'POST',
  url: '<my-server-url>',
  data: JSON.stringify(data),
  contentType: 'application/json',
  success: function(res) 
    console.log(res);
    $('#contactForm').find('.submissionMessage').html('<p>Thanks for registering!</p>').show();
  ,
  error: function(err) 
    console.log(err);
    $('#contactForm').find('.submissionMessage').html('<p>Something went wrong with the form submission.</p>').show();
  ,
  timeout: 10000
);

这是服务器端的 API:

function registerNewUser(req, res, next) 
  adminFunctions.newUser(req.body.email, req.body.password, req.body.name, req.body.first, req.body.last,
    req.body.phone, req.body.company, req.body.stateOrProvince, req.body.jobTitle, 
    req.body.token,
    function registeringUser(err, success) 
      var jsonResponse = 
        error: err,
        success: success
      ;
      var httpStatus = 201;
      if (err == 'Error: Failed to provide sign-up token.') 
        httpStatus = 401;
       else if (err == 'Error: User with that email already exists.') 
        httpStatus = 409;
       else if (err) 
        httpStatus = 500;
      
      res.status(httpStatus).json(jsonResponse);
    );

router.post('/users', rateLimit, registerNewUser);

router.options('/users', rateLimit, function(req, res) 
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'POST');
  res.setHeader('Access-Control-Allow-Credentials', true);
  res.setHeader('Access-Control-Max-Age', '86400'); // 24 hours
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
  res.end();
);

我已尝试在 AJAX 调用中将响应数据类型设为“jsonp”,但在它到达服务器之前出现 404 错误。

我还尝试使用 cors-anywhere API 在 AJAX 调用中为 url 添加前缀,但这也会在它到达服务器之前给我一个 404。

似乎发送成功响应的唯一事情是当我启用 Allow-Control-Allow-Origin Chrome 扩展时,这显然只能用于测试目的。

【问题讨论】:

需要允许 OPTIONS 方法。建议使用 cors 中间件 pckge @charlietfl — OPTIONS 方法 已被允许。这就是问题中最后 8 行代码的作用。 @Quentin 不在Access-Control-Allow-Methods 虽然 @charlietfl — 不需要允许预检 OPTIONS 请求,只需要明确的 OPTIONS 请求。 理想情况下,您不希望在Access-Control-Allow-Origin 上使用* 通配符。您可能希望列出执行请求的特定域。通过使用通配符,您会将自己暴露给其他不应提出请求的人。 【参考方案1】:

您有一堆添加 CORS 权限的函数调用:

 res.setHeader('Access-Control-Allow-Origin', '*');

……但这些都只是对预检 OPTIONS 请求的响应。

它们必须出现在 both 预检 OPTIONS 请求带有所请求资源的响应中。

您尚未将它们包含在对 POST 请求的响应中。


使用中间件最容易实现这一点,因此您不必重复调用来标头标题。 cors package 是预先编写的、成熟的、经过良好测试的中间件,您可以使用它而不是重新发明***。

【讨论】:

以上是关于“请求的资源上不存在‘Access-Control-Allow-Origin’标头” POST 请求成功后引发错误的主要内容,如果未能解决你的问题,请参考以下文章