2013-06-25 12 views
16

Ich habe einen grundlegenden AngularJS Service Setup wie so:AngularJS: POST-Daten an externen 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' 
     } 
    } 
}); 
}); 

und ich verwende es wie folgt aus:

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); 
}); 

Problem ein: User.update(), obwohl die Methode auf POST gesetzt ist, sendet weiterhin OPTIONS als Request-Methode.

Obwohl Chrome Dev-Tools den Request-Header Access-Control-Request-Methode meldet: POST wird auch gesendet (Nicht sicher, ob das irgendetwas bedeutet).

Problem zwei: Ich erhalte einen Fehler mit CORS trotz dieser Header in dem API-Code festgelegt hat:

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

Dieses Problem tritt nur wenn zeigt, wenn eine nicht-GET-Anfrage zu machen.

Wie ist der richtige Umgang damit? Ich habe auch JSONP untersucht, aber da es sich um eine REST-konforme API handelt, bin ich mir nicht sicher, wie ich die Probleme mit der GET-Unterstützung umgehen kann.

Antwort

14

Ihre zwei Probleme sind eigentlich ein Problem. Die OPTIONS-Anfrage ist Teil des CORS-Prozesses. Bei POST-Anfragen sendet der Browser zuerst einen OPTIONS-Aufruf, und der Server antwortet, wenn es in Ordnung ist, ihn auszuführen.

Wenn die OPTIONS-Anfrage fehlschlägt, zeigt Angular/Chrome den Grund in der Konsole an. Zum Beispiel:

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. 

Sie haben wahrscheinlich Access-Control-Allow-Header auf dem Server setzen, auch:

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

x-xrsf-Token sind für Winkel‘CSRF zu verhindern. Je nachdem, was Sie vom Client senden, müssen Sie möglicherweise mehrere Header hinzufügen.

Dies ist ein sehr guter Führer auf CORS: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

+0

Der Browser, der die OPTIONS-Anfrage und dann die POST-Anfrage sendet, war mein Problem. Der Server wurde nicht eingerichtet, um auf die anfänglichen OPTIONEN zu reagieren. Ich musste jedoch nichts mit x-xsrf-token tun. Benutzte den Code von hier, um alle notwendigen Header zu behandeln: http://stackoverflow.com/questions/13293157/backbone-slim-php-access-control-allow-headers-can-get-information-cant/13530329#13530329 –

+1

Das war genau mein Problem. Danke. Wenn du node/express benutzt, folge den "enable pre-flight" Anweisungen hier um cors arbeiten zu lassen: https://github.com/troygoodeNode-cors/ – JasonS

7

In AngularJS CORS, um die Arbeit müssen Sie auch die Standardeinstellungen des Winkel httpProvider überschreiben:

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

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

Gerade Einstellung useXDomain auf true ist nicht genug. AJAX Anfrage sind auch senden mit der X-Requested-With-Header, die sie als AJAX. Das Entfernen der Kopfzeile ist erforderlich, sodass der Server die eingehende Anforderung nicht zurückweist .

Hinweis: Antwort kann nur für ältere AngularJS Version vor 1.2. Ab 1.2 müssen Sie nichts mehr tun, um CORS zu aktivieren.

+6

Das war eigentlich nicht nötig, da ich Zugriff auf die habe api server und hinzugefügt 'header ('Access-Control-Erlaube-Header: X-Requested-With');' Ich nehme an, behebt das Problem, über das Sie sprechen. –

+0

Guter Tipp. Mir war nicht bewusst, dass ich den Header für allow-Header gesetzt habe. Danke. –

+0

vielleicht mussten Sie dies mit alten eckigen Versionen tun, aber ich weiß, dass Sie dies in eckigen 1.2.x nicht tun müssen. Die Antwort von @ Narretz funktioniert für mich. – JasonS

0

Besser, um dieses Problem auf dem Server zu lösen. Auf Apache kann man es so in einer .htaccess Datei lösen. Dies ist eine Quelle von Schmerzen für die eckige Entwicklung und kann auch in Winkelform gelöst werden, aber es ist wahrscheinlich nicht der beste Weg, dies zu tun.