web-dev-qa-db-fra.com

Un code d'état HTTP de 0 a-t-il une signification?

Il semble que lorsque vous créez un XMLHttpRequest à partir d'un script dans un navigateur, si le navigateur est configuré pour fonctionner en mode hors connexion ou si le câble de réseau est débranché, la demande se termine avec une erreur et avec le statut = 0. 0 n'est pas répertorié parmi les applications autorisées. Codes de statut HTTP.

Que signifie un code de statut de 0? Cela signifie-t-il la même chose dans tous les navigateurs et pour tous les utilitaires client HTTP? Cela fait-il partie de la spécification HTTP ou d'une autre spécification de protocole? Cela semble vouloir dire que la requête HTTP n'a pas pu être faite du tout, peut-être parce que l'adresse du serveur n'a pas pu être résolue.

Quel message d'erreur est approprié pour montrer à l'utilisateur? "Soit vous n'êtes pas connecté à Internet, soit le site Web rencontre des problèmes, soit il pourrait y avoir une faute de frappe dans l'adresse"?

J'ajouterais à cela que je vois le comportement dans FireFox lorsqu'il est défini sur "Travailler hors connexion", mais pas dans Microsoft Internet Explorer lorsqu'il est défini sur "Travailler hors connexion". Dans IE, l'utilisateur obtient une boîte de dialogue donnant la possibilité de se connecter. FireFox n'en informe pas l'utilisateur avant de retourner l'erreur.

Je demande ceci en réponse à une demande de "montrer un meilleur message d'erreur". Ce que fait Internet Explorer est bon. Il indique à l'utilisateur la cause du problème et lui donne la possibilité de le résoudre. Afin de donner un UX équivalent à FireFox, je dois en déduire la cause du problème et en informer l'utilisateur. Alors, que puis-je déduire de l'état 0? A-t-il une signification universelle ou ne me dit rien?

86
Mark Lutton

Réponse courte

C'est not un code de réponse HTTP, mais il est documenté par W3 comme une valeur valide pour l'attribut status. d'un XMLHttpRequest (et donc aussi d'un objet jqXHR, pour les utilisateurs de jQuery).

Il couvre toute une série de situations possibles dans lesquelles il n'y a pas de code de réponse HTTP réel à signaler, soit parce que vous n'avez pas envoyé la demande, vous l'avez explicitement abandonnée, la page est en cours de déchargement ou x s'est mal passé pour l'une des nombreuses valeurs possibles de x .

Longue réponse

Tout d'abord, réitérons que: 0 est not un code d'état HTTP. Il y en a une liste complète dans RFC 7231 Section 6.1 , qui n'inclut pas 0, et l'introduction de la section 6 indique clairement que

L'élément de code d'état est un code entier à trois chiffres

quel 0 n'est pas.

Cependant, 0 comme valeur de l'attribut status d'un XMLHttpRequest objet est documenté. De la documentation à http://www.w3.org/TR/XMLHttpRequest/#the-status-attribute :

4.7.1 L'attribut status

L'attribut status doit renvoyer le résultat de l'exécution de ces étapes:

  1. Si l'état est UNSENT ou OPENED, retourne 0.

  2. Si l'indicateur d'erreur est défini, renvoyez 0.

  3. Renvoie le code d'état HTTP.

Nous pouvons creuser plus profondément dans les spécifications et déterminer exactement ce que signifient ces conditions pour obtenir 0. De http://www.w3.org/TR/XMLHttpRequest/#states :

4,5 états

...

UNSENT (valeur numérique 0)

L'objet a été construit.

OPENED (valeur numérique 1)

La méthode open() a été appelée avec succès. Pendant cet état, les en-têtes de requête peuvent être définis à l'aide de setRequestHeader() et la requête à l'aide de la méthode send().

...

L'indicateur d'erreur indique un type d'erreur réseau ou une fin d'extraction. Il est initialement non réglé.

Il est également pertinent de noter que le prochain état possible après UNSENT et OPENED est HEADERS_RECEIVED:

HEADERS_RECEIVED (Valeur numérique 2)

Toutes les redirections (le cas échéant) ont été suivies et tous les en-têtes HTTP de la réponse finale ont été reçus. Plusieurs membres de réponse de l'objet sont maintenant disponibles.

En résumé, la réponse courte est que 0 est simplement ce qui est renvoyé par l'attribut status d'un objet XMLHttpRequest lorsqu'il n'y a pas de code d'état réel à renvoyer, car:

  • La demande n'a pas encore été envoyée, ou
  • La demande a été envoyée mais les en-têtes de la réponse n'ont pas encore été reçus, ou
  • Une des nombreuses circonstances possibles, répertoriées dans la documentation , ayant entraîné la définition de "l'indicateur d'erreur".

D'accord, mais quelles erreurs peuvent causer la création de ce "drapeau d'erreur" mystérieux? Si vous CTRL-F pour 'indicateur d'erreur' dans la documentation W3, vous constaterez qu'il obtient unset lors de l'envoi de la demande et qu'il ne reçoit jamais que set dans le cadre de l'algorithme pour "terminer la demande". En recherchant tous les lieux que l'algorithme est appelé, vous constaterez qu'il se produit lorsque:

  • La demande est ouverte (ou rouverte) avec la méthode open()
  • La requête est nettoyée (par exemple lorsque vous quittez la page)
  • La demande est abandonnée avec la méthode abort()
  • Une "erreur de demande" se produit, ce qui peut se produire lorsque l'une des situations suivantes se produit:

    • Une erreur réseau se produit, ce qui peut arriver si

      • Il y a une boucle de redirection infinie
      • Il y a

        Erreurs DNS, échec de la négociation TLS ou autre type d'erreur réseau

      • La demande était une demande CORS, et la réponse ne peut pas être partagée
    • Une erreur d'abandon se produit, ce qui ne peut se produire que si

      L'utilisateur final annule la demande

      peu importe ce que cela signifie. Je ne connais aucun navigateur qui indique aux utilisateurs quand AJAX) des demandes sont en cours et leur donne la possibilité de les annuler explicitement. Je pense donc que celui-ci est - du moins aujourd'hui - sans objet.

    • Une erreur de temporisation se produit, ce qui signifie, assez raisonnablement, que

      timeout n'est pas égal à 0 et, depuis le début de la demande, le nombre de millisecondes spécifié par timeout est passé

En ce qui concerne XMLHttpRequest, c'est tout.

Au-delà de XMLHttpRequest, je dirais que les bibliothèques HTTP dans des langages autres que JavaScript peuvent également utiliser un code d'état 0 de manière similaire, en tant que valeur par défaut lorsqu'aucun code d'état n'a été reçu du serveur.

145
Mark Amery

le statut 0 apparaît lorsqu'un appel ajax a été annulé avant d'obtenir la réponse en actualisant la page ou en demandant une URL inaccessible.

ce statut n'est pas documenté mais existe sur les appels ajax et makeRequest de gadget.io.

52
mnk

from documentation http://www.w3.org/TR/XMLHttpRequest/#the-status-attribute signifie qu'une demande a été annulée avant d'aller nulle part

5
Loki

Sache que c'est un vieux post. Mais ces problèmes existent toujours.

Voici certaines de mes conclusions sur le sujet, grossièrement expliquées.

"Statut" 0 signifie l'une des 3 choses suivantes, conformément à la spécification XMLHttpRequest:

  • la résolution du nom DNS a échoué (par exemple, lorsque la fiche réseau est retirée)

  • le serveur n'a pas répondu (a.k.a. inaccessible ou non correspondant)

  • la demande a été abandonnée à cause d'un problème CORS (l'avortement est effectué par l'agent utilisateur et suit un test OPTIONS en échec avant le vol).

Si vous voulez aller plus loin, plongez au cœur de XMLHttpRequest. Je suggère de lire la séquence de mise à jour à l'état prêt ([0,1,2,3,4] est la séquence normale, [0,1,4] correspond à l'état 0, [0,1,2,4] signifie pas de contenu. envoyé qui peut être une erreur ou non). Vous pouvez également attacher des écouteurs à xhr (onreadystatechange, onabort, onerror, ontimeout) pour obtenir des détails.

A partir de la spécification ( XHR Living spec ):

const unsigned short UNSENT = 0;
const unsigned short OPENED = 1;
const unsigned short HEADERS_RECEIVED = 2;
const unsigned short LOADING = 3;
const unsigned short DONE = 4;
4
Obotor

Depuis iOS 9, vous devez ajouter "Paramètres de sécurité du transport d'application" à votre fichier info.plist et autoriser "Autoriser les chargements arbitraires" avant de demander un service Web HTTP non sécurisé. J'ai eu ce problème dans l'une de mes applications.

0
Nirav