2015-12-31 56 views
2

在我的angular2应用程序中,我尝试进行跨域ajax调用。虽然调用成功,但在angular2端,错误回调总是被触发而不是成功回调。下面是代码:如何使angular2在成功的预检请求后正确触发正确的回调

this.http.post('http://localhost:3000/tasks/add', '["' + task + '"]', {headers: headers}).subscribe(
     data => null, 
     err => alert("err"), 
     () => alert("succ") 
    ); 

在浏览器控制台,我看到这一点:

XMLHttpRequest cannot load http://localhost:3000/tasks/add. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. 

服务器端在的NodeJS实现,它包括以下处理预检

router.options('/add', (req, res, next) => { 
    console.log('!OPTIONS'); 
    var headers = {}; 
    // IE8 does not allow domains to be specified, just the * 
    // headers["Access-Control-Allow-Origin"] = req.headers.origin; 
    headers["Access-Control-Allow-Origin"] = "*"; 
    headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS"; 
    headers["Access-Control-Allow-Credentials"] = false; 
    headers["Access-Control-Max-Age"] = '86400'; // 24 hours 
    headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept"; 
    res.writeHead(200, headers); 
    res.end(); 
}); 

的上面的服务器代码已成功执行,并且客户端确实在预检选项请求之后发送了发布请求。

我的问题是,我可以做什么在angular2,使其触发成功回调,它应该?

更新:

我在这里附上截图和它采取了在Chrome中。它的底部显示了CORS错误消息,但是最上面的部分显示请求和200一致。事实上,它确实通过了,因为我在服务器端收到了选项和发布请求。

enter image description here

更新2:上的NodeJS(服务器)侧

试过明示-CORS,还是一样。 (我的初始代码已经处理了预检选项请求 - 代码可以在本文的原始部分中找到,除非我的原始nodejs代码中有错误,否则express-cors预计不会改变任何内容。)

下面是我用快递-CORS尝试了代码,基本相同,其NPM页面上有什么:

var express = require('express'); 
var cors = require('express-cors') 

var router = express.Router(); 
router.use(cors({ 
    allowedOrigins: [ 
     '*' 
    ] 
})) 

更新3:

神秘解决了!在我的原始代码中,我只在选项响应中设置了CORS标头,但没有在选项请求之后响应帖子请求。这似乎仍然允许整个过程在应用程序级别完成 - 因为服务器端确实收到了请求并处理了数据,但由于响应没有包含正确的标头,角度出现错误。我修改了我的代码,不仅在选项响应中发送CORS头文件,还发送了后期响应,现在角度触发成功回调。

+0

对于更新3,所以你不需要任何Angular2的预检CORS选项发送,只是为了返回来自Express的POST响应头上的CORS?今天我遇到了麻烦,我肯定我错过了一些东西。我正在使用ASP.NET MVC作为API服务器,并且在我的控制器上使用了[EnableCors(origin:“*”,headers:“*”,methods:“*”)]',但我仍然收到错误就像你在截图中一样。 –

+0

你也调用过config.EnableCors();在你的注册方法? 'App_Start/WebApiConfig.cs'中的 –

+0

我确实在Register方法中有'config.EnableCors();'在顶部。 –

回答

0

实际上,是与快递CORS的专用模块称为cors。你可以像这样安装它:npm install cors

这就是说,没有什么在做浏览器,因为一切都罩跨域请求下进行:

  • 浏览器发送Origin
  • 使用简单或预检请求
  • 检查CORS响应头以查看您的请求是否可以执行

此链接可以帮助您了解CORS如何在眉间工作sers:http://restlet.com/blog/2015/12/15/understanding-and-using-cors/

简而言之,这是一个服务器问题,而不是Angular应用程序中的问题。您可以在Chrome开发工具标签网络中检查响应内容(标题),以查看响应中是否存在CORS标头(包括简单和预检)。

+0

我会尝试这个cors模块并让你知道。谢谢!看起来令人费解的是,服务器在请求选项后确实收到了实际的请求,这表明它没有问题。另外,发布请求是为了将一些数据插入数据库并插入数据,所有这些都表明cors已成功完成。这就是为什么错误回调被角度触发的原因。 –

+0

尝试过并没有工作。我将代码添加到我的OP中作为“更新2”。 –

+1

我看了一下你的截图,但是在POST请求的响应头里看不到'Access-Control-Allow-Origin'头。这其实是一个问题... –

0

您的错误消息看起来不像预检请求成功。预检请求由浏览器在实际请求之前自动完成,如果预检请求导致错误,就像您的情况一样,实际的请求根本就没有发生。

试试这个服务器上,而不是:

headers["Access-Control-Allow-Origin"] = "http://localhost"; 
+1

谢谢!根据nodejs日志,它确实收到选项后的实际发布请求。这似乎是预检成功了,否则它不会发送发布请求。数据也被插入数据库,所以操作成功。这就是为什么在客户端看到错误回调被触发的原因。目前,服务器响应预检,并将允许的来源设置为*,这应该覆盖本地主机。我会尝试你所建议的,而不是*,我会专门将它设置为localhost。我会让你知道的。 –

+1

你说得对,那很奇怪。 –

+0

试过并没有工作。我使用chrome进行了屏幕截图更新。 –

相关问题