J'essaie d'envoyer des demandes HTTP de mon application angular.js à mon serveur, mais je dois résoudre certaines erreurs CORS.
La requête HTTP est effectuée à l'aide du code suivant:
functions.test = function(foo, bar) {
return $http({
method: 'POST',
url: api_endpoint + 'test',
headers: {
'foo': 'value',
'content-type': 'application/json'
},
data: {
bar:'value'
}
});
};
Le premier essai s'est soldé par des erreurs CORS. J'ai donc ajouté les lignes suivantes à mon script PHP:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, X-Auth-Token, content-type');
La première erreur est maintenant éliminée.
Maintenant, la console développeur de Chrome me montre les erreurs suivantes:
angular.js: 12011 OPTIONS http: // localhost: 8000/test (fonction anonyme)
423ef03a: 1 XMLHttpRequest ne peut pas charger http: // localhost: 8000/test . La réponse pour le contrôle en amont a un code d'état HTTP non valide 400
et la requête réseau ressemble à ce que j'attendais (état HTTP 400
est également attendu):
Je ne peux pas imaginer comment résoudre la chose (et comment comprendre) pourquoi la demande sera envoyée sur localhost en tant que OPTIONS
et aux serveurs distants en tant que POST
. Existe-t-il une solution pour résoudre ce problème étrange?
La demande OPTIONS
est appelée demande de pré-vol , qui fait partie de = Partage de ressources entre origines (CORS) . Les navigateurs l'utilisent pour vérifier si une demande est autorisée à partir d'un domaine particulier comme suit:
POST
avec le application/json
type de contenuOPTIONS
HTTP 200 OK
réponse à la demande de pré-vol, il envoie la demande réelle, POST
dans votre casLes navigateurs n'envoient pas les requêtes avant le vol dans certains cas, ce sont les soi-disant simples demandes et sont utilisés dans les conditions suivantes:
- L'une des méthodes autorisées:
GET
HEAD
POST
- Hormis les en-têtes définis automatiquement par l'agent utilisateur (par exemple, Connection, User-Agent, etc.), les seuls en-têtes qui peuvent être définis manuellement sont les suivants:
Accept
Accept-Language
Content-Language
Content-Type
(mais notez les exigences supplémentaires ci-dessous)DPR
Downlink
Save-Data
Viewport-Width
Width
- Les seules valeurs autorisées pour l'en-tête Content-Type sont:
application/x-www-form-urlencoded
multipart/form-data
text/plain
- Aucun écouteur d'événement n'est enregistré sur un objet
XMLHttpRequestUpload
utilisé dans la demande; ceux-ci sont accessibles en utilisant leXMLHttpRequest.upload
propriété.- Aucun objet
ReadableStream
n'est utilisé dans la demande.
Ces demandes sont envoyées directement et le serveur traite simplement avec succès la demande ou les réponses avec une erreur au cas où elle ne correspondrait pas aux règles CORS. Dans tous les cas, la réponse contiendra les en-têtes CORS Access-Control-Allow-*
.
Les navigateurs envoient les demandes avant le vol si la demande réelle ne correspond pas à la demande simple conditions, le plus souvent:
application/xml
ou application/json
, etc., sont utilisésGET
, HEAD
ou POST
POST
est d'un autre type de contenu que application/x-www-form-urlencoded
, multipart/form-data
ou text/plain
Vous devez vous assurer que la réponse à la demande pré-vol possède les attributs suivants :
200 OK
Access-Control-Allow-Origin: *
(un caractère générique *
permet une demande depuis n'importe quel domaine, vous pouvez utiliser n'importe quel domaine spécifique pour restreindre l'accès ici bien sûr)De l'autre côté, le serveur peut refuser la requête CORS simplement en envoyant une réponse à la requête - pré-vol avec les attributs suivants:
2XX
)200 OK
), mais sans en-tête CORS (c'est-à-dire Access-Control-Allow-*
)Voir documentation sur Mozilla Developer Network ou par exemple tutoriel CORS de HTML5Rocks pour plus de détails.
Donc, dans votre cas, l'en-tête approprié est présent, il vous suffit de vous assurer que le code d'état HTTP de la réponse pré-vol est 200 OK
ou un autre succès (2XX
) .
J'ai rencontré un problème très similaire lors de l'écriture d'une application Angular 2 - qui utilise un serveur NODE pour l'API.
Étant donné que je développe sur ma machine locale, je continuais à rencontrer des problèmes d'en-tête Cross Origin, lorsque j'essayais de POST vers l'API depuis mon Angular app.
La définition des en-têtes (dans le serveur de noeud) comme ci-dessous a fonctionné pour les demandes GET, mais mes demandes PUT ont continué à publier des objets vides dans la base de données.
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT');
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type,
Origin, Authorization, Accept, Client-Security-Token, Accept-
Encoding, X-Auth-Token, content-type');
Après avoir lu article de Dawid Ferenczy , j'ai réalisé que la requête PREFLIGHT envoyait des données vides à mon serveur, et c'est pourquoi mes entrées de base de données étaient vides, alors j'ai ajouté cette ligne dans le serveur NODE JS:
if (req.method == "OPTIONS")
{
res.writeHead(200, {"Content-Type": "application/json"});
res.end();
}
Alors maintenant, mon serveur ignore la demande PREFLIGHT, (et retourne le statut 200, pour que le navigateur sache que tout est groovy ...) et de cette façon, la vraie demande peut passer et je reçois de vraies données publiées sur ma base de données!
Mettez juste
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
header("HTTP/1.1 200 ");
exit;}
au début de votre application côté serveur et ça devrait aller.
Pour une application Spring Boot, pour activer la demande de cors, utilisez @CrossOrigin(origins = "*", maxAge = 3600)
sur votre contrôleur respectif.