Angular资源如何保持ajax头文件并同时启用cors

在我的ng资源文件中,我启用了ajax头文件:

var app = angular.module('custom_resource', ['ngResource']) app.config(['$httpProvider', function($httpProvider) { //enable XMLHttpRequest, to indicate it's ajax request //Note: this disables CORS $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest'; }]) app.factory('Article', ['$resource', function($resource) { return $resource('/article/api/:articleId', {articleId: '@_id'}, { update: {method: 'PUT'}, query: {method: 'GET', isArray: true} }) }]) 

因此,我可以分开ajax和非ajax请求和响应(发送像res.json(data) json数据,或发送像res.render('a.html')整个HTML页面

例如,在我的error handling程序中,我需要决定渲染error.html页面或仅发送错误消息:

 exports.finalHandler = function(err, req, res, next) { res.status(err.status || 500) var errorMessage = helper.isProduction() ? '' : (err.message || 'unknown error') if (req.xhr) { res.json({message: errorMessage}) } else { res.render(dir.error + '/error_page.ejs') } } 

但是现在我需要对其他站点进行CORS请求。 保持ajax头可以做CORS请求吗? 或者我可以从服务器识别ajax和非ajax请求的其他方式?

如果我的问题还不清楚,请参考有关angular和CORS的文章http://better-inter.net/enabling-cors-in-angular-js/

基本上,我们需要删除xhr头来为其他服务器启用cors,但是我需要为我自己的服务器头

编辑2:

今天我试图整合谷歌地图,我得到这个错误:

 XMLHttpRequest cannot load http://maps.googleapis.com/maps/api/geocode/json?address=Singapore&sensor=false. Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers. 

如果你正在使用最新版本的angular.js,你可以这样做

首先,添加xhr标题(你所做的是正确的)

  $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 

然后在你的谷歌地图searchfunction

 var searchAddress = function(address) { var params = {address: address, sensor: false}; //Note: google map rejects XHR header $http.get(google_map_web_api_url, {params: params, headers: {'X-Requested-With': undefined}}) .success(function(data, status, headers, config) { }) .error(function(data, status, headers, config) { }) } 

传入的headersconfiguration参数将删除每个请求库的xhr,这意味着你的ng资源请求是不变的

在XHR请求上设置自定义标题会触发预检请求。

所以,它不会禁用CORS,但是您的服务器很可能不会处理预检请求。

从这个post启发: https : //remysharp.com/2011/04/21/getting-cors-working

解决scheme应该是使用cors模块,并在路由之前将以下内容添加到您的node.js代码中:

 var corsOptions = { origin: true, methods: ['GET', 'PUT', 'POST'], allowedHeaders: ['X-Requested-With','Content-Type', 'Authorization'] }; app.options('*', cors(corsOptions)); //You may also be just fine with the default options 

你可以阅读更多: https : //github.com/expressjs/cors

你可以尝试使用Cors包

首先,为了解决您主要关心的问题,是否可以在保持ajax头部的同时执行CORS请求? :答案是肯定的 ,只要您访问的网站允许来自您或任何其他外部客户端的请求。

你写了:

 //Note: this disables CORS $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest'; 

但我不明白你的意思,它“ 禁用CORS ”。 X-Requested-With头部不是标准头部,并且向请求(由浏览器产生)添加非标准头部的已知效果是触发了飞行前请求[ 3 ]。

如果您感兴趣的其他网站将其服务器设置为拒绝处理来自其自己的域的请求,那么无论您是否设置了该标头,请求都会失败。

似乎一切工作正常,为您的请求发送给你自己的服务器。 否则,您可以通过在服务器响应中附加Access-Control-Allow-Origin标头来解决问题,如下所示:

  1. 如果您需要允许来自特定域的请求

    response.set("Access-Control-Allow-Origin", "one-host-domain, your-host-domain, some-other-host-domain"); // second argument is a comma-delimited list of allowed domains

    (实际上检查请求对象的原点可能会更好,如果它允许基于在预定列表中的存在,则发回完全相同的原点)。

  2. 如果您需要允许所有请求而不pipe其来源

    response.set("Access-Control-Allow-Origin", "*");

这应该做的,我希望它清除你的怀疑。

使用AJAX时处理CORS的更多信息: 0,1和2 。


编辑

在评论交stream之后,我join以下几点来进一步支持这个答案。

就像今天一样,需要在客户端 – 服务器系统中禁用/启用CORS的唯一方面就是服务器。 所有现代浏览器默认都允许跨源请求,并且您不需要额外执行任何操作来支持该function。 我知道你正在添加一个自定义头来区分AJAX请求和其余的? AFAIK,这个头文件没有改变浏览器的请求。

以下是浏览器如何处理所有跨域请求:对于所有的请求方法 (但通常不包括GET ),浏览器使用OPTION方法发送一个请求前请求。 如果目标服务器允许,则发送实际请求,否则请求失败。 在服务器拒绝回应的情况下,没有任何东西或任何图书馆可以对此进行处理。 这是我自己的经验。

有三种解决scheme出现在我的脑海里:1.请求网站pipe理员在CORS中启用x-requested- header。 2.使用代理服务器。 3.发送无x请求的请求

这篇文章应该说明CORS是如何工作的以及如何制作CORS请求。 特别是“简单请求”部分和“访问控制”部分,尤其是访问控制允许标题描述在这种情况下是重要的。

正如它所说的:对于简单的请求访问控制允许来源就足够了。 但是,如果请求包含自定义标头(默认不包含的标头,例如x-requested-with标头),则会触发预检请求,服务器对此请求的响应应该在访问控制允许中启用此自定义标头通过将其值设置为“*”或自定义标题( x-requested-with )的名称。

希望它更清楚一点。