J'appelle POST sur une API tierce avec laquelle j'ai travaillé via la fonction $ .ajax de jQuery. Cependant, lorsque je passe l'appel, j'obtiens le message d'erreur suivant: XMLHttpRequest cannot load http://the-url.com. The request was redirected to 'http://the-url.com/anotherlocation', which is disallowed for cross-Origin requests that require preflight.
J'ai vu dans ce message qu'il s'agissait peut-être d'un bogue Webkit, alors je l'ai essayé dans Firefox (je développe sous Chrome) et j'ai obtenu le même résultat. J'ai déjà essayé cela sur Chrome et Firefox et j'ai le même résultat.
Per this post , j’ai également essayé d’utiliser jsonp en définissant la propriété crossDomain
de la fonction $ .ajax sur true
et en définissant la valeur dataType
sur jsonp
. Mais cela a provoqué une erreur de 500 serveur interne.
Lorsque je lance Chrome avec l'option --disable-web-security, je n'ai aucun problème. Cependant, si je lance le navigateur normalement, j'obtiens l'erreur.
Donc, je suppose que cela pourrait en quelque sorte être une question en 2 parties. Que puis-je faire pour faire cette demande interdomaine? Si JSONP est la solution, comment puis-je déterminer si l'API tierce est configurée correctement pour prendre en charge cela?
EDIT: Voici la capture d'écran lorsque je passe l'appel avec la sécurité du navigateur désactivée: https://drive.google.com/file/d/0Bzo7loNBQcmjUjk5YWNWLXM2SVE/edit?usp=sharing
Voici le screenchost lorsque je passe l'appel avec la sécurité du navigateur activée (comme d'habitude): https://drive.google.com/file/d/0Bzo7loNBQcmjam5NQ3BKWUluRE0/edit?usp=sharing
La solution que j'ai proposée consistait à utiliser cURL (comme mentionné par @waki), mais une version légèrement modifiée prenant en charge SOAP. Ensuite, au lieu d'appeler AJAX vers l'API tierce (configurée de manière incorrecte), j'appelle vers mon fichier PHP local, qui passe ensuite un appel SOAP à l'API tierce. et renvoie les données dans mon fichier PHP où je peux ensuite les traiter. Cela me permet d'oublier la SCRO et toutes les complexités qui y sont associées. Voici le code (pris et modifié depuis this question, mais sans l’authentification).
$post_data = "Some xml here";
$soapUrl = "http://yoursite.com/soap.asmx"; // asmx URL of WSDL
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: http://yoursite.com/SOAPAction",
"Content-length: " . strlen($post_data),
); //SOAPAction: your op URL
$url = $soapUrl;
// PHP cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); // the SOAP request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
/* Check for an error when processing the request. */
if(curl_errno($ch) != 0) {
// TODO handle the error
}
curl_close($ch);
// TODO Parse and process the $response variable (returned as XML)
À votre première question,
Que puis-je faire pour faire cette demande interdomaine?
Les en-têtes de requête suivants sont d'abord envoyés au serveur. Sur la base des en-têtes de réponse, le UserAgent, c'est-à-dire le navigateur ici, ignorera la réponse (le cas échéant) et ne la retournera pas au rappel XHR lorsque les en-têtes ne s'additionnent pas.
Origin: http://yourdomain.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-Custom-Header
Votre serveur devrait alors répondre avec les en-têtes suivants:
Access-Control-Allow-Origin: http://yourdomain.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: X-Custom-Header
Exemple tiré de - https://stackoverflow.com/a/8689332/1304559
Vous pouvez utiliser des outils tels que l'onglet Réseau de Fiddler ou Web Inspector (Chrome) ou l'onglet Réseau de Firebug pour rechercher les en-têtes que le serveur renvoie en réponse à votre demande.
L'URL du serveur d'API tiers doit répondre avec les valeurs prises en charge. Si ce n'est pas le cas, c'est votre problème.
Ne peut pas être d'une grande aide en cas d'erreur du serveur JsonP 500, car il indique Erreur interne du serveur
METTRE À JOUR
J'ai vu vos captures d'écran, quelques choses à noter ici
HTTP POST
est utiliséAccess-Control
trouvé dans la réponse des deux modes. Avec le deuxième code de statut en tant que 302
Origin
est null
. Je pense donc que le fichier HTML est ouvert à partir du système de fichiers plutôt que d'un site Web.Activer JSONP
Pourquoi JSONP ne fonctionne-t-il pas? La configuration du service Web (spécifiée par ASMX) n'a pas activé le mode GET
pour la demande. JSONP ne fonctionne pas avec POST
.
Pourquoi 200
avec la sécurité désactivée?
La demande POST est directement appelée, sans aucune variable OPTIONS
ni commande de contrôle en amont, de sorte que le serveur répond simplement en retour.
Pourquoi 302
code d'état avec sécurité activée?
Commençons par expliquer comment cela se produit lorsque l’indicateur de sécurité n’est pas désactivé (par défaut). La demande OPTIONS
est renvoyée à l'URL. L’URL doit répondre avec une liste de méthodes HTTP pouvant être utilisées, à savoir GET
, POST
, etc. Le code d’état de cette demande OPTIONS
doit être 200
.
Dans le cas présent, une redirection est appelée lors de cette opération. Et la redirection pointe vers un gestionnaire d’erreurs personnalisé pour une erreur de serveur HTTP. Je crois qu'il s'agit d'une erreur 404
qui est interceptée et redirigée. [Cela pourrait être dû au fait que le gestionnaire personnalisé est défini sur ResponseRedirect
au lieu de ResponseRewrite
] La raison de 404
est l'accès inter-domaine n'est pas activé.
Si le traitement personnalisé des erreurs était désactivé, le code HTTP 500
aurait été renvoyé. Je pense que le problème peut être résolu en consultant les journaux du serveur immédiatement après le lancement d'une requête inter-domaines. Il sera bon de rechercher dans les journaux du serveur des erreurs autres que celle-ci, le cas échéant.
Solution possible
Pour permettre l'accès, il existe deux manières - détaillées ici . Ou ajoutez directement les en-têtes de contrôle d'accès à la section customheaders
du fichier web.config
.
Lorsque l'accès entre domaines est activé, le serveur doit répondre à OPTIONS et autoriser le traitement de la demande. Cela devrait renvoyer HTTP 200
à moins qu'il y ait d'autres erreurs. Mais le rappel ajax ne pourra pas accéder à la réponse. Cela ne peut être fait maintenant que si Access-Control-Allow-Origin
est défini sur "*" ou la valeur de l'en-tête de la requête Origin
, et le Access-Control
si nécessaire. Et le rappel ajax recevra la réponse comme prévu.
Le troisième point, null Origin
. Cela posera un problème si la valeur de l'en-tête de la requête Origin
est renvoyée sous la forme Access-Control-Allow-Origin
. Mais je suppose que vous déplacerez votre page HTML sur un serveur Web. Cela ne devrait donc pas poser de problème.
J'espère que cela t'aides!
Vous pouvez utiliser cURL? Avec Ajax vous envoyez des données à votre gestionnaire (sur votre serveur, appelez callback.php) . Dans votre fichier (callback.php), utilisez cURL avec vos données:
$post_data = array(
'key' => 'key',
'test' => 'text'
);
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($curl, CURLOPT_URL, 'http://www.domain.com/');
$return = json_decode(trim(curl_exec($curl)), TRUE);
curl_close($curl);
dans votre variable $ return, vous obtenez vos données.