在尝试从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
Authorization
和Content-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.url
replace为任何实际的sign_in
url。
浏览器需要从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服务,那么
- 停止节点服务器。
- npm安装cors
-
将以下行添加到您的server.js
var cors = require('cors')
app.use(cors())//在variables声明之后使用它