2013-06-25 26 views
16

我有一个基本的AngularJS服务设置像这样:AngularJS:POST数据到外部REST API

app.factory('User', function($resource) { 
return $resource('http://api.mysite.com/user/:action:id/:attr', {}, { 
    history: { 
     method: 'GET', 
     params: { 
      attr: 'history' 
     } 
    }, 
    update: { 
     method: 'POST', 
     params: { 
      name: 'test' 
     } 
    } 
}); 
}); 

,我使用它是这样的:

User.history({id: 'testID'}, function(data) { 
    console.log('got history'); 
    console.log(data); 
}); 
User.update({id: 'me'}, function(data) { 
    console.log('updated'); 
    console.log(data); 
}); 

问题一: User.update (),尽管将该方法设置为POST,但仍将发送OPTIONS作为请求方法。

虽然Chrome开发工具会报告请求标题访问控制请求方法:也发送POST(不知道这是否意味着什么)。

问题二:我不断收到一个错误与CORS,尽管有这些头的API代码设置:

header('Access-Control-Allow-Origin: *'); 
header("Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS"); 

此问题仅虽然显示出来,如果做一个非GET请求。

处理这个问题的正确方法是什么?我也研究过JSONP,但是由于这是一个RESTful API,我不确定如何解决只有GET支持的问题。

回答

14

你的两个问题实际上是一个问题。 OPTIONS请求是CORS流程的一部分。对于POST请求,浏览器首先发送一个OPTIONS调用,如果可以执行,服务器会响应。

如果OPTIONS请求失败,Angular/Chrome向您显示控制台中的原因。例如:

OPTIONS https://*** Request header field Content-Type is not allowed by Access-Control-Allow-Headers. angular.min.js:106 

XMLHttpRequest cannot load https://***. Request header field Content-Type is not allowed by Access-Control-Allow-Headers. 

你可能必须在服务器上设置访问控制允许接头,太:

header('Access-Control-Allow-Headers: Content-Type, x-xsrf-token') 

X-xrsf令牌是角”,以防止CSRF。您可能需要添加更多标题,具体取决于您从客户端发送的内容。

这里是CORS很好的指导意义:https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

+0

发送OPTIONS请求和POST请求的浏览器是我的问题所在。服务器未设置为响应初始选项。尽管我不需要对x-xsrf-token做任何事情。使用这里的代码来处理所有必要的标题:http://stackoverflow.com/questions/13293157/backbone-slim-php-access-control-allow-headers-can-get-information-cant/13530329#13530329 –

+1

这正是我的问题。谢谢。如果您使用node/express,请按照下面的“启用预先飞行”说明获取cors工作:https://github.com/troygoode/node-cors/ – JasonS

7

在AngularJS使CORS的工作,你还必须覆盖角度httpProvider的默认设置:

var myApp = angular.module('myApp', [ 
    'myAppApiService']); 

myApp.config(['$httpProvider', function($httpProvider) { 
     $httpProvider.defaults.useXDomain = true; 
     delete $httpProvider.defaults.headers.common['X-Requested-With']; 
    } 
]); 

只设置useXDomain为真是不足够的。 AJAX请求也是 与X-Requested-With标头一起发送,这表明它们是 AJAX。删除头是必要的,所以服务器不会拒绝 传入的请求。

注意:答案只适用于旧的AngularJS版本之前的1.2。使用1.2及以上版本,您无需执行任何操作即可启用CORS。

+6

实际上这并不是必需的,因为我可以访问api服务器并添加了'header('访问控制 - 允许 - 标题:X-Requested-With');'我认为这可以解决您所讨论的问题。 –

+0

好的提示。我不知道设置允许标题头。谢谢。 –

+0

也许你必须使用旧的角度版本来做到这一点,但我知道在角度1.2.x中,你不需要这样做。以下@ Narretz的答案适用于我。 – JasonS

0

更好的解决服务器上的这个问题。在apache上,你可以在.htaccess文件中这样解决它。这是一个角度发展的痛苦来源,可以在角度上解决,但它可能不是最好的方式来做到这一点。

Header set Access-Control-Allow-Origin "*" 
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type" 
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"