116 votes

Comment empêcher les requêtes ajax de suivre les redirections en utilisant jQuery

Je utilise les fonctions ajax de jQuery pour accéder à un service web, mais le serveur, au lieu de renvoyer une réponse avec un code d'état décrivant un problème, redirige la requête vers une page avec un en-tête 200, décrivant le problème. Je ne peux pas apporter de modifications à cela, donc je dois le résoudre côté client d'une manière ou d'une autre.

Exemple : Une requête est envoyée à une URL qui n'est pas trouvée, donc je reçois une redirection 302 vers un autre emplacement. Une nouvelle requête est envoyée, et je reçois un 200 OK, empêchant ainsi l'appel d'erreur de se déclencher.

Y a-t-il un moyen d'empêcher la requête ajax de suivre les redirections et d'activer plutôt un callback, de préférence la méthode d'erreur. Alternativement, est-il possible de détecter si une redirection s'est produite côté client ?

0 votes

9 votes

Il est étrange que votre backend rapporte un 302 pour un non trouvé, au lieu d'un 404.

1 votes

105voto

Oleg Points 136406

Je trouve votre question intéressante, mais le problème dans son ensemble me semble plus être un malentendu. Au moins je vais essayer d'expliquer ma compréhension du problème.

La redirection silencieuse (transparente) fait partie de la spécification XMLHttpRequest (voir ici notamment les mots "... suivre la redirection de manière transparente ..."). La norme mentionne seulement que l'agent utilisateur (le navigateur web) peut empêcher ou notifier de certains types de redirections automatiques, mais ce n'est pas une partie de XMLHttpRequest. C'est une partie de la configuration du client HTTP (configuration du système d'exploitation) ou la configuration du navigateur web. Donc jQuery.ajax ne peut pas avoir d'option où vous pouvez empêcher la redirection.

Vous pouvez voir que la redirection HTTP fait partie du protocole HTTP et non pas de XMLHttpRequest. C'est à un autre niveau d'abstraction ou de la pile réseau. Par exemple les données de XMLHttpRequest peuvent être récupérées à partir du proxy HTTP ou du cache du navigateur local, et c'est une partie du protocole HTTP. Majoritairement le serveur qui fournit les données et non pas le client peut influencer le cache.

Vous pouvez comparer l'exigence de votre question avec l'exigence de prévenir le changement d'adresse IP du serveur web ou le changement de l'itinéraire IP pendant la communication. Toutes ces choses peuvent être intéressantes dans certains scénarios, mais elles font partie d'un autre niveau de la pile de communication et ne peuvent pas être gérées par jQuery.ajax ou XMLHttpRequest.

La norme XMLHttpRequest indique que la configuration du client peut avoir des options qui empêchent les redirections. Dans le cas du "monde Microsoft", que je connais mieux, vous pouvez regarder la fonction WinHttpSetOption qui peut être utilisée pour définir l'option WINHTTP_OPTION_DISABLE_FEATURE avec la valeur WINHTTP_DISABLE_REDIRECTS. Une autre façon est d'utiliser l'option WINHTTP_OPTION_REDIRECT_POLICY avec la valeur WINHTTP_OPTION_REDIRECT_POLICY_NEVER. Une autre fonctionnalité que l'on peut utiliser dans Windows est la fonction WinHttpSetStatusCallback qui peut définir une fonction de rappel pour recevoir des notifications comme WINHTTP_CALLBACK_FLAG_REDIRECT.

Il est donc possible de mettre en œuvre vos exigences en général, mais la solution ne sera probablement pas indépendante du système d'exploitation ou du navigateur web et ne se fera pas au niveau de jQuery.ajax ou XMLHttpRequest.

3 votes

Réponse excellente avec une grande perspicacité ! J'ai de l'expérience avec curl, pour lequel vous pouvez définir des drapeaux similaires à ceux que vous mentionnez. J'espérais que de telles instructions pourraient être transmises au navigateur, mais d'après votre réponse, je comprends que le comportement attendu serait de suivre les redirections comme si la demande initiale avait été envoyée à l'emplacement assigné par le serveur.

0 votes

@Jørgen : Vous êtes les bienvenus ! Dans la plupart des scénarios, la redirection n'est pas du tout un problème. Vous ne décrivez pas le contexte dans lequel vous utilisez jQuery.ajax et si vous avez un contrôle total sur le serveur web auquel vous envoyez la requête. Il est donc difficile de vous donner d'autres conseils qui pourraient vraiment résoudre votre problème.

0 votes

Je ne contrôle pas le côté serveur, j'ai bien peur. Je suppose que ma meilleure option est d'analyser ou de valider le contenu de la réponse.

27voto

Jake Feasel Points 10341

Je ne crois pas que cela soit possible. La bibliothèque sous-jacente (XHR) effectue la nouvelle requête de manière transparente. Cela étant dit, ce que j'ai fait dans ces situations (généralement un problème de durée de session qui me conduit vers une page de connexion) est renvoyer un en-tête de réponse personnalisé. J'ai également mis en place un gestionnaire ajax global qui vérifie la présence de cet en-tête et répond de manière appropriée lorsqu'il est présent (par exemple, redirigeant toute la page vers l'écran de connexion).

Si cela vous intéresse, voici le code jQuery que j'utilise pour surveiller cet en-tête personnalisé :

/* redirige la fenêtre principale lorsque la requête AJAX indique que la session a expiré sur le backend. */
function checkSession(event, xhr, ajaxOptions)
{
    if (xhr.readyState == 4)
    {
        if(xhr.getResponseHeader("Login-Screen") != null && xhr.getResponseHeader("Login-Screen").length)
        {
            window.location.href='sessionExpired.html'; //quelque chose d'autre
        }
    }
}

$(document).ajaxComplete(checkSession)

1 votes

Merci, je suppose que je vais devoir me contenter d'une approche similaire, en analysant la réponse.

2voto

Je ne peux pas ajouter grand-chose à la sagesse perspicace des codeurs précédents qui ont répondu, mais je vais ajouter un cas spécifique que d'autres pourraient trouver utile à connaître.

J'ai rencontré cette redirection silencieuse 302 dans le contexte de SharePoint. J'ai un code client Javascript simple qui interroge un sous-site SharePoint, et s'il reçoit une réponse HTTP 200, il se relocalise sur ce site, via window.location. Si cela reçoit autre chose, il informe l'utilisateur que le site n'existe pas.

Cependant, dans le cas où le site existe mais que l'utilisateur n'a pas la permission, SharePoint redirige silencieusement vers une page AccessDenied.aspx. SharePoint a déjà effectué le protocole d'authentification HTTP 401 au niveau du serveur/ferme - l'utilisateur a accès à SharePoint. Mais l'accès au sous-site est géré, je suppose, en utilisant des indicateurs de base de données de quelque sorte. La redirection silencieuse contourne ma clause "else", donc je ne peux pas afficher mes propres erreurs. Dans mon cas, ce n'est pas un blocage - c'est un comportement prévisible et cohérent. Mais c'était un peu surprenant, et j'ai appris quelque chose sur les requêtes HTTP dans le processus!

0voto

netadictos Points 4988

Je suppose que vous recevez une réponse 200 car la deuxième fois il n'y a pas de redirection, car la page 404 n'expire pas, elle est sauvegardée dans le cache. Autrement dit, la deuxième fois, le navigateur vous donne la page en cache. Il y a une propriété "cache" dans l'ajax jQuery. http://api.jquery.com/jQuery.ajax/

Vous devriez le mettre à "false"

-2voto

ipr101 Points 15337

Je ne suis pas sûr que cela s'appliquera dans votre cas, mais vous pouvez écrire du code pour répondre à des codes d'état spécifiques dans une fonction AJAX -

$.ajax({
    url: '/admin/secret/data',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    statusCode: {
        200: function (data) {
            alert('302: Est survenu');
            // Associer les données JSON à l'interface utilisateur
        },
        401: function (data) {
            alert('401: Est survenu');
            // Gérer l'erreur 401 ici.
        }
    }
});

9 votes

Je ne pense pas que cela s'applique car l'OP a dit qu'il toujours obtient un code d'état 200 en raison de la redirection qui se produit en arrière-plan.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X