CORS标头仅在角度资源请求中丢失

时间:2015-09-02 17:35:20

标签: node.js express cors

我在localhost上运行了一个工作节点/ express后端。我正在构建一个需要从goodreads api获取数据的项目应用程序。当我执行请求时,我得到:

1

服务器端,一切正常。我启用了CORS,当我检查标题时,' Access-Control-Allow-Origin'检查Firefox和Chrome开发工具中的标题后,我的服务器上的所有内容都可用。但是,当我通过$ resource提出请求时,'允许访问...'在我的标题中不存在。以下是资源的代码:

Cross-Origin Request Blocked: 
The Same Origin Policy disallows reading the remote resource at 
https://www.goodreads.com/book/title.json?author=Arthur+Conan+Doyle&key=[my_key]&title=Hound+of+the+Baskervilles. 
(Reason: CORS header 'Access-Control-Allow-Origin' missing).1 <unknown>

我通过ng-click调用fetch,除了收到CORS错误外,一切正常。谁能指出我正确的方向?我是角色的新手,我的怀疑是我的资源请求或配置中的某些内容存在问题,但我似乎无法在文档或其他stackoverflow问题中找到解决问题的方法。

更新3:这不是本地主机问题。我尝试将它推送到我的域并使用一个简单的按钮,它向OpenBooks api运行xhr请求,问题变得更糟。它通过Openshift托管,现在是“允许 - 控制 - 访问 - x&#39;即使我的服务器上的其他文件,标题也消失了。真的开始在这里撞到我的头。我正在删除Angular标签,因为它与Angular无关。

更新2 :我在安装&#39; Allow-Control-Allow-Origin&#39; Chrome扩展程序。我的问题是我在localhost上运行这个问题吗?或者还有其他事情发生了吗?如果没有扩展名,标题仍未设置。

更新:我从早上8点开始就一直在努力,但仍然没有运气。我尝试使用Angular的$ http重写请求,并使用Javascript&#39; xhr按照HTML5 Rocks | Using Cors的示例重写请求,并且我仍然对每种方法都有相同的问题。就像我说的那样,我的服务器上的文件可以获得必要的头信息,但是当我向其他站点发出请求时它就会中断。

我开始认为这可能不是一个角度问题,但我真的不知道。为了安全起见,这里是我添加到Express以启用CORS的代码,包括app.use,这样你就可以知道我在哪里调用它:

.factory('goodReads', function($resource) {
    return $resource('https://www.goodreads.com/book/title.json');
})
.controller('AddBookSelectorController', function($resource, goodReads) {
    this.fetch = function() {
        var key = '[my_key]';
        var data = goodReads.query({author: 'Arthur Conan Doyle', key: key, title: 'Hound of the Baskervilles'});
        console.log(data);
    };
});

编辑:以下是API请求中的标头:

请求标题

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, Content-Length");
    res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    res.header("Access-Control-Allow-Credentials", "true");
    next();
});
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);

响应标头

Host: www.goodreads.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101     Firefox/40.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://localhost:3000/
Origin: http://localhost:3000
Connection: keep-alive

来自我服务器的.js文件的标头:

请求

Cache-Control: max-age=0, private, must-revalidate
Content-Encoding: gzip
Content-Length: 686
Content-Type: application/json; charset=utf-8
Date: Wed, 02 Sep 2015 17:20:35 GMT
Etag: "a2be782f32638d2a435bbeaf4b01274a-gzip"
Server: Server
Set-Cookie: csid=BAhJIhg1MzgtNTk4NjMzNy0wNzQ4MTM5BjoGRVQ%3D--afed14b563e5a6eb7b3fa9005de3010474230702; path=/; expires=Sun, 02 Sep 2035 17:20:33 -0000
locale=en; path=/
_session_id2=fd45336b8ef86010d46c7d73adb5f004; path=/; expires=Wed, 02 Sep 2015 23:20:35 -0000; HttpOnly
Status: 200 OK
Vary: Accept-Encoding,User-Agent
X-Content-Type-Options: nosniff, nosniff
X-Frame-Options: ALLOWALL
X-Request-Id: 1K8EJWG30GWDE4MZ4R5K
X-Runtime: 2.277972
X-XSS-Protection: 1; mode=block

响应:

Host: localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101   Firefox/40.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://localhost:3000/
Cookie: _ga=GA1.1.1924088292.1439681064; connect.sid=s%3AB4O0Up9WF5iqkfky__I0XCiBD2aMATlq.gbJUC9GseqnJvRTEIbcwxD6cwFQeL7ljNScURCJ5As0
Connection: keep-alive
If-Modified-Since: Wed, 02 Sep 2015 17:08:40 GMT
If-None-Match: W/"886-14f8f0828c1"
Cache-Control: max-age=0

1 个答案:

答案 0 :(得分:3)

我想这个问题暴露了我的无知,但也许这会帮助像我这样的其他新手。在获得 CORs in Action 的副本并使用Flickr API完成第一个示例后,我终于找到了问题。

我的问题与后端,Angular,jQuery的.ajax方法或xhr无关。我的所有请求都已正确格式化。 问题是我试图使用的API没有在他们的服务器上启用COR。 O.o只要我将数据类型更改为jsonp,一切都会通过。

无论如何,对于像我这样的新手,如果你遇到这个问题,这里有一些指示可以帮助你:

<强> 1。不要假设您使用的API已启用COR

我不知道为什么,但是我盲目地选择了两个没有启用COR的API,这对我来说是个大惊小怪。我之前从未遇到过这个问题,因为我用API完成的工作一直来自像Flickr那样启用了CORs的大公司。如果他们没有在他们的服务器上设置Access-Control-Allow-Origin,您可以请求他们启用它并在此期间使用JSONP。

如果API在最后有一个回调选项,那么这是一个好兆头,您应该使用JSONP来处理您的请求。 JSONP的工作原理是将您的请求包装在回调中并利用脚本标记的功能。脚本可以从任何域中提取其他脚本,因此它可以作为获取数据的黑客。这是一个帮助我的好链接。 Exactly What is JSONP? | CameronSpear.com

<强> 2。检查响应标题

我被此欺骗了,但请记住,您对外部API请求的响应标头是他们的服务器的响应,而不是您的响应。如果您的服务器上启用了COR,您向其他人发出请求并且浏览器会自动在请求标头中向您发送信息,这无关紧要。请记住,出于安全原因,所有这些检查都是由浏览器完成的,因此它会根据您的ajax调用在请求端为您完成繁重的工作。如果访问控制 - 无论响应标头中是否显示,它们都没有启用COR。如果您正在处理前端并请求其他人的数据,则无法对其进行任何操作。使用JSONP,您的问题将消失(可能)。

对我来说,整个惨败开始了,因为我对来自我的服务器的响应感到困惑,并为他们的服务器提供了响应。我在我自己的服务器上正确启用了COR,但我认为它没有将原始信息附加到请求标头,这就是它在响应头中不存在的原因。实际上,一切都正常,但API服务器没有启用它。

所以花了一天,但吸取了许多教训。希望我浪费时间帮助其他人解决他们的COR问题。请注意,我的问题是堆栈不可知,因此无论您如何发出请求,检查响应标头是您遇到COR问题时要采取的第一个行动方案。在那之后,我建议查看请求本身的错误。

查看上面的图书或来自同一作者的此链接以获取更多帮助,尤其是涉及非简单请求时HTML5 Rocks | Using CORs