web-dev-qa-db-fra.com

Angular $ http envoie des options au lieu de PUT / POST)

J'essaye de mettre à jour/insérer des données dans une base de données MySQL via un backend PHP. Je construis le Front End avec AngularJS et j'utilise le $http service de communication avec l'API REST.

Ma configuration ressemble à ceci:

Je configure l'en-tête via $ httpProvider:

 $httpProvider.defaults.withCredentials = true;
 $httpProvider.defaults.headers = {'Content-Type': 'application/json;charset=utf-8'};

Et le POST-Call ressemble à ceci:

   return $http({
      url: url,
      method: "POST",
      data: campaign
    });

La console de développement de Chrome me montre ceci:

enter image description here

Lorsque je change de POST en PUT, j'envoie un appel OPTIONS à la place d'un PUT. Et le type de contenu bascule simplement en content-type.

Les données de ma demande sont envoyées sous forme d'objet:

enter image description here

Comment définir correctement mon en-tête?


EDIT:

Le PHP backend définit certains en-têtes:

   $e->getResponse()
              ->getHeaders()
              ->addHeaderLine('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

   $e->getResponse()
              ->getHeaders()
              ->addHeaderLine('Access-Control-Allow-Origin', '*');

Est-ce qu'il manque quelque chose?

61
Bastian Gruber

Ok, je l'ai résolu.

Quel était le problème?
Le flux de travail CORS pour DELETE, PUT et POST est le suivant:

enter image description here

Ce qu'il fait, c'est:

  1. Vérifier quelle demande va être faite
  2. Si c'est POST, PUT ou DELETE
  3. Il envoie d’abord une requête OPTION pour vérifier si le domaine à partir duquel la requête est envoyée est identique à celui du serveur.
  4. Si ce n'est pas le cas , il souhaite qu'un en-tête d'accès soit autorisé à envoyer cette demande.

Important ici: Une demande OPTIONS n'envoie pas les informations d'identification .

Donc, mon serveur principal a refusé la demande PUT.

Solution:
En plaçant ceci à l'intérieur du .htaccess fichier

RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ blank.php [QSA,L]
Header set Access-Control-Allow-Origin "http://sub.domain:3000"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"

Après cela, créez un fichier .php vide appelé blank.php dans le dossier public.

EDIT: Comme l’a souligné un intervenant, au lieu de créer un fichier PHP) vide, vous pouvez ajouter cette règle de réécriture à votre fichier .htaccess \;

RewriteRule ^(.*)$ $1 [R=200,L,E=HTTP_Origin:%{HTTP:Origin}]]

Pour préciser:

  1. J'ai déjà envoyé l'en-tête de contrôle d'accès
  2. Ce qui a résolu ce sont les deux premières lignes, et
  3. Access-Control-Allow-Origin du sous-domaine spécifique avec le port

Le meilleur site que j'ai pu trouver sur en savoir plus sur la SCRO .

71
Bastian Gruber

Vous n'avez pas besoin de spécifier votre $http en-têtes manuellement, tout est fait pour vous dans les coulisses et ils sont automatiquement réglés sur application/json pour POST et PUT demandes de type. Donc tout ce que vous devriez faire est

$http.post(url, data);
$http.put(url, data);
4
Dan Moldovan