2013-06-25 25 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"