我正在尝试从HP Alm的REST API中获取一些数据 . 它适用于小卷曲脚本 - 我得到了我的数据 .
现在使用JavaScript,fetch和ES6(或多或少)似乎是一个更大的问题 . 我一直收到此错误消息:
Fetch API无法加载 . 对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头 . 因此不允许来源“http://127.0.0.1:3000”访问 . 响应具有HTTP状态代码501.如果不透明响应满足您的需要,请将请求的模式设置为“no-cors”以获取禁用CORS的资源 .
我知道这是因为我试图从我的localhost中获取该数据,解决方案应该使用CORS . 现在我以为我确实这样做了,但不管怎样它要么忽略我在 Headers 中写的内容,要么问题是别的?
那么,是否存在实施问题?我做错了吗?遗憾的是我无法检查服务器日志 . 我真的有点卡在这里 .
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属性控制 .
4 回答
当客户端URL和服务器URL不匹配(包括端口号)时,会发生此错误 . 在这种情况下,您需要为CORS启用服务,这是跨源资源共享 .
如果您正在托管Spring REST服务,那么您可以在博客文章CORS support in Spring Framework中找到它 .
如果您使用Node.js服务器托管服务,那么
停止Node.js服务器 .
npm安装cors
将以下行添加到server.js
这个答案涵盖了很多方面,因此它分为三个部分:
如何避免CORS预检
如何使用CORS代理来解决“No Access-Control-Allow-Origin header”问题
如何修复“Access-Control-Allow-Origin标头不能是通配符”问题
How to avoid the CORS preflight
问题中的代码触发CORS预检 - 因为它发送
Authorization
标头 .https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
即使没有它,
Content-Type: application/json
Headers 也会触发预检 .什么“预检”意味着:在浏览器尝试问题代码中的
POST
之前,它将首先向服务器发送OPTIONS
请求,以确定服务器是否选择接收包含以下内容的跨源POST
Authorization
和Content-Type: application/json
Headers .要使用
curl
正确测试,您需要模拟浏览器发送的预检OPTIONS
请求:...
https://the.sign_in.url
替换为您的实际sign_in
URL .浏览器需要从
OPTIONS
请求中看到的响应必须包含以下标头:如果
OPTIONS
响应不包含这些标头,那么浏览器将在那里停止,甚至从未尝试发送POST
请求 . 此外,响应的HTTP状态代码必须是2xx(通常为200或204) . 如果是任何其他状态代码,浏览器将停在那里 .问题中的服务器使用501状态代码响应
OPTIONS
请求,这显然意味着它正在尝试表明它没有实现对OPTIONS
请求的支持 . 在这种情况下,其他服务器通常以405“方法不允许”状态代码进行响应 .因此,如果服务器使用405或501或200或204之外的任何其他响应或者如果没有响应,则您永远无法从前端JavaScript代码直接向该服务器发出
POST
请求那些必要的响应 Headers .避免在问题中触发案件预检的方法是:
如果服务器不需要
Authorization
请求标头,而是(例如)依赖于嵌入在POST
请求正文中的身份验证数据或作为查询参数如果服务器不要求
POST
正文具有Content-Type: application/json
媒体类型,而是接受POST
正文作为application/x-www-form-urlencoded
,其参数名为json
(或其他),其值为JSON数据How to use a CORS proxy to get around “No Access-Control-Allow-Origin header” problems
如果您不控制服务器,您的前端JavaScript代码正在向其发送请求,而该服务器响应的问题只是缺少必要的
Access-Control-Allow-Origin
标头,您仍然可以通过提出请求来完成工作CORS代理 . 为了说明它是如何工作的,首先是一些不使用CORS代理的代码:catch
块被击中的原因是浏览器阻止该代码访问从https://example.com
返回的响应 . 浏览器这样做的原因是,响应缺少Access-Control-Allow-Origin
响应头 .现在,这是完全相同的示例,但只是添加了CORS代理:
Note: If https://cors-anywhere.herokuapp.com is down or unavailable when you try it, then see below for how to deploy your own CORS Anywhere server at Heroku in just 2-3 minutes.
上面的第二个代码片段可以成功访问响应,因为获取请求URL并将其更改为https://cors-anywhere.herokuapp.com/https://example.com-只需在其前面添加代理URL - 导致请求通过该代理进行,然后:
将请求转发给
https://example.com
.收到
https://example.com
的回复 .将
Access-Control-Allow-Origin
标头添加到响应中 .将带有添加的标头的响应传递回请求的前端代码 .
然后,浏览器允许前端代码访问响应,因为具有
Access-Control-Allow-Origin
响应头的响应是浏览器看到的 .您可以使用https://github.com/Rob--W/cors-anywhere/中的代码轻松运行自己的代理 .
您还可以使用5个命令轻松地将自己的代理部署到Heroku,只需2-3分钟:
运行这些命令后,您最终将拥有自己运行的CORS Anywhere服务器,例如https://cryptic-headland-94862.herokuapp.com/ . 那么,不要在前面添加
https://cors-anywhere.herokuapp.com
请求URL,而是在前缀中添加您自己实例的URL;例如,https://cryptic-headland-94862.herokuapp.com/https://example.com .So if when you go to try to use https://cors-anywhere.herokuapp.com, you find it’s down (有时会这样),然后考虑获得一个Heroku帐户(如果你还没有)并花2或3分钟完成上述步骤,在Heroku上部署你自己的CORS Anywhere服务器 .
无论您是运行自己的还是使用https://cors-anywhere.herokuapp.com或其他开放代理,即使请求是触发浏览器执行CORS预检
OPTIONS
请求的解决方案,此解决方案仍然有效 - 因为在这种情况下,代理也会发回Access-Control-Allow-Headers
和Access-Control-Allow-Methods
使预检成功所需的 Headers .How to fix “Access-Control-Allow-Origin header must not be the wildcard” problems
对于包含凭据的请求,如果
Access-Control-Allow-Origin
响应标头的值为*
,则浏览器不会让您的前端JavaScript代码访问响应 . 相反,该情况下的值必须与您的前端代码的原点完全匹配,http://127.0.0.1:3000
.请参阅MDN HTTP访问控制(CORS)文章中的Credentialed requests and wildcards .
如果您控制要发送请求的服务器,那么处理这种情况的常用方法是配置服务器以获取
Origin
请求标头的值,并将其回显/反映回Access-Control-Allow-Origin
响应的值头 . 例如,使用nginx:但这只是一个例子;其他(Web)服务器系统提供类似的方式来回显原始值 .
Chrome CORS插件显然只是简单地在浏览器看到的响应中注入
Access-Control-Allow-Origin: *
标头 . 如果插件更智能,它将要做的是将假的Access-Control-Allow-Origin
响应标头的值设置为前端JavaScript代码http://127.0.0.1:3000
的实际原点 .因此,即使是测试,也要避免使用该插件 . 这只是一种分心 . 如果您想测试从服务器获得的响应而没有浏览器过滤它们,那么最好使用
curl -H
,如上所述 .至于问题中
fetch(…)
请求的前端JavaScript代码:删除这些行 .
Access-Control-Allow-*
标头是响应标头 . 你永远不想在请求中发送它们 . 唯一的影响就是触发浏览器进行预检 .使用dataType:'jsonp',适合我 .
删除这个: