在尝试从REST API获取数据时,请求的资源上没有“Access-Control-Allow-Origin”标头

我试图从HP Alm的REST API中获取一些数据。 它用一个小curl脚本很好 – 我得到我的数据。

现在用JavaScript来做,取和ES6(或多或less)似乎是一个更大的问题。 我不断收到此错误消息:

抓取API无法加载。 对预检请求的响应不会通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。 原因' http://127.0.0.1:3000 '因此不被允许访问。 响应的HTTP状态码为501.如果一个不透明的响应满足您的需要,请将请求的模式设置为“no-cors”,以取消禁用CORS的资源。

我知道这是因为我试图从我的本地主机获取数据,解决scheme应该使用CORS。 现在我以为我确实是这样做的,但是不知怎么的,要么忽略我在标题中写的东西,要么问题是其他的东西?

那么,是否有执行问题? 我做错了吗? 我不能检查服务器日志不幸的。 我真的有点卡在这里。

function performSignIn() { let headers = new Headers(); headers.append('Content-Type', 'application/json'); headers.append('Accept', 'application/json'); headers.append('Access-Control-Allow-Origin', 'http://localhost:3000'); headers.append('Access-Control-Allow-Credentials', 'true'); headers.append('GET', 'POST', 'OPTIONS'); headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password)); fetch(sign_in, { //mode: 'no-cors', credentials: 'include', method: 'POST', headers: headers }) .then(response => response.json()) .then(json => console.log(json)) .catch(error => console.log('Authorization failed : ' + error.message)); } 

我正在使用Chrome。 我也尝试使用该Chrome CORS插件,但后来我收到另一个错误信息:

当请求的凭证模式为'include'时,响应中'Access-Control-Allow-Origin'标头的值不能是通配符'*'。 原因' http://127.0.0.1:3000 '因此不被允许访问。 由XMLHttpRequest发起的请求的凭证模式由withCredentials属性控制。

这个答案涵盖了很多地方,所以分为三个部分:

  • 如何避免CORS预检
  • 如何使用CORS代理来解决“无访问控制 – 允许 – 源头”问题
  • 如何解决“Access-Control-Allow-Origin头部不能是通配符”的问题

如何避免CORS预检

问题中的代码会触发一个CORS预检,因为它会发送一个Authorization标头。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests

即使没有, Content-Type: application/json头也会触发预检。

什么“预检”意味着:在浏览器在问题的代码中尝试POST之前,它将首先向服务器发送OPTIONS请求,以确定服务器是否正在select接收包含交叉源的POST AuthorizationContent-Type: application/json头文件。

它用一个小curl脚本很好 – 我得到我的数据。

要正确testingcurl ,您需要模拟浏览器发送的预检OPTIONS请求:

 curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \ -H 'Access-Control-Request-Method: POST' \ -H 'Access-Control-Request-Headers: Content-Type, Authorization' \ "https://the.sign_in.url" 

…用https://the.sign_in.urlreplace为任何实际的sign_inurl。

浏览器需要从OPTIONS请求中看到的响应必须包含如下所示的头文件:

 Access-Control-Allow-Origin: http://127.0.0.1:3000 Access-Control-Allow-Methods: POST Access-Control-Allow-Headers: Content-Type, Authorization 

如果OPTIONS响应不包含这些头文件,那么浏览器就会停在那里,甚至不会尝试发送POST请求。 此外,响应的HTTP状态代码必须是2xx–通常为200或204.如果是其他任何状态代码,则浏览器将在此处停止。

问题中的服务器用一个501状态码来响应OPTIONS请求,这显然意味着它试图表明它没有实现对OPTIONS请求的支持。 在这种情况下,其他服务器通常使用405“不允许的方法”状态码进行响应。

所以如果服务器用405或者501或者200或者204以外的任何其他东西来响应这个OPTIONS请求,或者如果没有响应,那么你永远无法从你的前端JavaScript代码直接向服务器发出POST请求那些必要的响应标题。

避免在问题中触发事件的方法是:

  • 如果服务器不需要Authorization请求头,而是(例如)依靠embedded在POST请求主体中的validation数据或作为查询参数
  • 如果服务器不要求POST主体具有Content-Type: application/json媒体types,而是接受POST主体作为application/x-www-form-urlencoded ,其参数的名称为json (或其他) JSON数据

如何使用CORS代理来解决“无访问控制 – 允许 – 源头”问题

如果您不控制服务器,则您的前端JavaScript代码正在向其发送请求,而来自该服务器的响应问题仅仅是缺lessAccess-Control-Allow-Origin标头,您仍然可以使用 – 通过CORS代理进行请求。 为了展示这是如何工作的,首先这里是一些不使用CORS代理的代码:

 const url = "https://example.com"; // site that doesn't send Access-Control-* fetch(url) .then(response => response.text()) .then(contents => console.log(contents)) .catch(console.log("Can't access " + url + " response. Blocked by browser?")) 

当客户端URL和服务器url不匹配包括端口时,会发生此错误。 在这种情况下,您需要启用您的跨域资源共享CORS服务。

如果你正在举办春季rest服务,那么你可以在这里find它。

https://spring.io/blog/2015/06/08/cors-support-in-spring-framework

如果您正在使用节点服务器托pipe服务,那么

  1. 停止节点服务器。
  2. npm安装cors
  3. 将以下行添加到您的server.js

    var cors = require('cors')

    app.use(cors())//在variables声明之后使用它