【发布时间】:2013-12-14 12:22:06
【问题描述】:
我正在尝试访问我无法控制的 REST 服务。第一个问题是该服务不包含 Access-Control-Allow-Origin 标头,如果我理解正确,这个问题会立即将我限制为 JSONP。
此外,默认情况下,此服务发送 XML 而不是 JSON,尽管它能够发送 JSON。我认为它应该响应我的 Accept 标头,负责服务的人员说它会查看我的 Content-Type。这意味着我需要执行 POST 而不是 GET(尽管当我只是获取一些静态数据时 get 更有意义,对吧?)。
虽然我很固执,但我会先尝试我的 Accept 标头。由于 Angular 只接受 JSON,我希望它默认使用 Accept: application/json 标头,但它没有,它忽略了我手动设置它的尝试:
app.config(['$httpProvider', function($httpProvider){
console.log($httpProvider.defaults.headers.common);
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.headers.post['Access-Control-Max-Age'] = '1728000';
$httpProvider.defaults.headers.common['Access-Control-Max-Age'] = '1728000';
$httpProvider.defaults.headers.common['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.useXDomain = true;
}]);
我在实际资源中再次这样做:
return $resource('http://foo.com/getStuff', {}, {
fetch: {
method:'JSONP',
params: params,
headers: {
'Accept':'application/json, text/javascript',
'Content-Type':'application/json; charset=utf-8'
},
isArray:false,
callback: 'JSON_CALLBACK'
}
});
但是,请求标头仍然包含Accept: */*。
我的问题是:为什么?为什么 Angular 会忽略我的标题?以及如何让它使用正确的标题?
还有:有没有办法在 POST 中使用 JSONP?
编辑: 最初我使用 Angular 1.0.7,但我只是在 1.2.3 上尝试过,得到了相同的结果。标题被忽略,但每个人都声称这是这样做的方法。
我也试过直接用$http而不是用$resource来做,结果是一样的。
编辑 2: 这是JSFiddle。它是匿名的,不使用我的真实服务器,但使用 Firebug/开发人员工具,您可以验证它在两个调用中都发送 Accept: */*,尽管我多次尝试设置 application/json 标头。这是我真正的问题。在我的真实服务器上,尽管我的真实服务器能够发送 JSON,但我得到了 XML 结果。
(目前真实服务器是否支持jsonp不太重要。这个虚拟服务器显然不支持,但没关系。我只关心标题。)
编辑 3:我尝试了以下建议的两种解决方案:
$http.defaults.headers.common['Accept'] = 'application/json, text/javascript';
$http.defaults.transformRequest.push(function (data, headersGetter) {
headersGetter().Accept = "application/json, text/javascript";
return data;
});
我已经分别尝试了这两种说法。在控制器中,然后在 http 调用本身之前的服务中。还是不行。
有人可以给我一个 JsFiddle 吗?
编辑 4: 我注意到当我使用 GET 而不是 JSONP 时,Accept 标头是正确的。但随后响应被拒绝,因为它没有正确的标题。
JSONP 调用应该有什么样的标头?因为 JSONP 调用中有更多的标头,但没有将其标识为 JSONP。服务器是否必须有明确的 JSONP 支持才能工作?我突然意识到我对 jsonp 的了解还不够。
【问题讨论】:
-
您确定您使用的 WebService 以有效的JSONP 响应您的请求吗?我注意到的第一件事是您没有正确设置
callback查询参数。$resource应该是:..., params: {callback: 'JSON_CALLBACK'}, ...如果可能,请提供 Plunk 或 JSFiddle,以便我们可以使用您的代码。 -
我确定它不会以有效的 JSONP 响应。它向我发送 XML,大概是因为我没有发送正确的标头。我目前的主要问题是正确设置标头,以便服务知道向我发送 json 或 jsonp。
-
我知道,这就是为什么我建议首先查看您的 REQUEST URL(-:。每个使用 JSONP 响应的 WebService 都在 URL 查询字符串中搜索
callback,并且永远不会使用 JSONP 响应因为它需要callback参数值来执行此操作。它基本上提取callback参数值并将:<<callback_param_value>>(<<response_JSON_object>>);作为application/javascript发送给您 -
@mcv 您不能为 JSONP 请求设置标头或使用 POST 方法。
-
JSONP 只是CORS 的一种老套且过时的方式:)
标签: http angularjs jsonp angularjs-resource