web-dev-qa-db-fra.com

AngularJS: POST Données vers externe REST API

J'ai une configuration de base du service AngularJS comme ceci:

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

et je l'utilise comme ça:

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

Problème 1: User.update (), bien que la méthode soit définie sur POST, continue à envoyer des OPTIONS en tant que méthode de requête.

Bien que Chrome Dev Tools rapporte l’en-tête de la demande Access-Control-Request-Method: Le test POST est également envoyé (vous ne savez pas si cela signifie quoi que ce soit).

Deuxième problème: Je continue à avoir une erreur avec CORS, malgré le fait que ces en-têtes soient définis dans le code de l'API:

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

Ce problème n'apparaît que si vous faites une demande non-GET.

Quelle est la bonne façon de gérer cela? J'ai aussi examiné JSONP, mais comme il s'agit d'une API RESTful, je ne sais pas comment résoudre les problèmes uniquement avec le support GET.

16
Lucas Raines

Vos deux problèmes sont en réalité un problème. La demande OPTIONS fait partie du processus CORS. Pour les demandes POST, le navigateur envoie d'abord un appel OPTIONS, puis le serveur répond s'il est autorisé à l'exécuter. 

Si la demande OPTIONS échoue, Angular/Chrome vous en indique le motif dans la console. Par exemple: 

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. 

Vous devez probablement également définir des en-têtes Access-Control-Allow sur le serveur:

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

x-xrsf-token est pour angular 'pour prévenir CSRF. Vous devrez peut-être ajouter d'autres en-têtes, en fonction de ce que vous envoyez du client.

Voici un très bon guide sur CORS: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

14
Narretz

Dans AngularJS pour que CORS fonctionne, vous devez également écraser les paramètres par défaut de la variable angulaire httpProvider:

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

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

Il ne suffit pas de définir useXDomain sur true. Les demandes AJAX sont également send avec l'en-tête X-Requested-With, qui les indique comme étant AJAX. La suppression de l'en-tête est nécessaire pour que le serveur ne rejette pas la demande entrante.

Remarque : La réponse ne fonctionne que pour les versions antérieures à AngularJS antérieures à 1.2. Avec 1.2 et plus, vous n'avez rien à faire pour activer CORS.

7

Mieux vaut résoudre ce problème sur le serveur. Sur Apache, vous pouvez le résoudre comme ceci dans un fichier .htaccess. Ceci est une source de douleur pour le développement angulaire et peut être résolu également mais ce n'est probablement pas la meilleure façon de le faire. 

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"
0
rotato poti