我在端口6000
上运行了一个节点Web服务器(express)。
调用http://localhost:6000/
时,index.html
将提供给客户端,该客户端有一个运行的脚本logic.js
:
var xhr = new XMLHttpRequest();
var url = 'http://localhost:4000/endpoint';
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log('endpoint');
callback(xhr.responseText);
}
};
xhr.send(JSON.stringify({'key': 'value'}));
在端口4000
上运行另一个快速服务器。
服务器设置一个端点,它只返回请求主体提交的内容:
app.route('/segment')
.post(bodyParser.json(), function(req, res) {
res.set('Access-Control-Allow-Origin', '*');
res.send(req.body);
});
当我访问http://localhost:6000/
时,我在浏览器控制台中看到了这一点:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:4100/segment. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
在原型设计过程中有没有办法绕过这个?
答案 0 :(得分:4)
您的端点可能不提供OPTIONS HTTP方法,浏览器用它来检查CORS标头(在它们发出真实请求之前)。
如果您在开发和生产中需要不同的CORS标头,我认为最好的方法是添加一个新的后端配置选项,其中包含允许来源的值,并从一些全局响应过滤器中提供它们。
答案 1 :(得分:1)
您已设置xhr.setRequestHeader('Content-type', 'application/json');
,因此这是preflighted request(经验法则:对于HTML表单的enctype
属性而言不是有效值的Content-Type将触发预先要求)。
您的服务器端代码仅设置Access-Control-Allow-Origin
标头以响应POST请求。您需要编写服务器端代码以响应预检OPTIONS请求。
答案 2 :(得分:1)
以下是解决此问题的几种方法:
最佳:CORS标头(需要更改服务器)
CORS(跨域资源共享)是一种服务器说“我会接受您的请求,即使您来自不同的来源。”这需要服务器的合作 - 所以如果您不能修改服务器(例如,如果您使用的是外部API),这种方法将无效。修改服务器以添加标头Access-Control-Allow-Origin:*以从任何地方启用跨源请求(或指定域而不是*)。这应该可以解决你的问题。
第二选择:代理服务器
如果无法修改服务器,则可以运行自己的代理。如果该代理与您的页面不在同源,则此代理可以返回Access-Control-Allow-Origin标头。
您不会向某个远程服务器发送API请求,而是向您的代理发出请求,代理会将它们转发到远程服务器。以下是一些代理选项。
第三选择:JSONP(需要服务器支持)
如果CORS和代理服务器不适合您,JSONP可能会有所帮助。您基本上使用回调参数发出GET请求:
(get)http://api.example.com/endpoint?callback=foo 服务器将JSON回复包含在对回调的函数调用中,您可以在其中处理它:
foo({“你的”:“json”,这里:true}) 存在一些缺点,特别是JSONP仅支持GET请求,并且您仍然需要协作服务器。