400 BAD demande la signification du code d'erreur HTTP?

346

J'ai une demande JSON que je poste sur une URL HTTP.

Doit-il être traité comme 400où le requestedResourcechamp existe mais "Roman"est une valeur non valide pour ce champ?

[{requestedResource:"Roman"}] 

Cela devrait-il être traité comme 400où le "blah"champ n'existe pas du tout?

[{blah:"Roman"}]
Phénix
la source
34
Peut-être 402 , s'ils veulent vraiment pouvoir envoyer la valeur Roman, ils ont juste besoin de vous payer plus :)
Jason Sperske
Un vrai scénario où j'ai vu cela - j'ai fait un appel PUT pour ajouter des données. J'ai refait un appel en utilisant le même corps de demande et j'ai obtenu un 400 qui m'a dit qu'une demande précédente était déjà en cours de traitement. Il est normal que notre système prenne un certain temps pour ajouter ces données.
MasterJoe2

Réponses:

361

Un 400 signifie que la demande a été mal formée. En d'autres termes, le flux de données envoyé par le client au serveur n'a pas suivi les règles.

Dans le cas d'une API REST avec une charge utile JSON, 400 sont généralement, et je dirais correctement, utilisés pour indiquer que le JSON n'est pas valide d'une manière ou d'une autre selon les spécifications de l'API pour le service.

Selon cette logique, les deux scénarios que vous avez fournis devraient être de 400.

Imaginez plutôt qu'il s'agissait de XML plutôt que de JSON. Dans les deux cas, le XML ne passerait jamais la validation du schéma - soit à cause d'un élément non défini ou d'une valeur d'élément incorrecte. Ce serait une mauvaise demande. Même affaire ici.

Vidya
la source
3
Je suis d'accord avec vous jusqu'à "Selon cette logique, les deux scénarios que vous avez fournis devraient être de 400". Je ne pense pas que le contenu du JSON soit important ici. Lorsque vous dites mal formé, j'aimerais croire que cela résout les problèmes de format des données que vous envoyez, par exemple si vous sautez un champ dans le JSON, vous devriez en avoir 400.
Geethanga
2
Il existe un ensemble décent de codes de réponse REST sur restapitutorial.com/httpstatuscodes.html . Cela peut également dépendre de la façon dont vous souhaitez gérer une demande valide telle qu'une méthode 406 (non acceptable) ou 405 non autorisée. Cependant, 400 est approprié car "La demande n'a pas pu être comprise par le serveur en raison d'une syntaxe incorrecte. Le client NE DEVRAIT PAS répéter la demande sans modifications."
Andrew Scott Evans du
3
Ainsi, «La demande n'a pas pu être comprise par le serveur en raison d'une syntaxe mal formée» peut être soit la demande (par exemple, l'un des en-têtes HTTP est mal formé) ou les données portées par la demande (par exemple, une valeur JSON est manquante) ?
MC Emperor
2
Vidya dit que "le XML ne passerait jamais la validation du schéma". Le fait est que les analyseurs XML font la distinction entre un document bien formé (c'est-à-dire syntaxiquement sain) et valide (c'est-à-dire sémantiquement sain, par exemple selon un schéma). La description du code 400 est "la requête n'a pas pu être comprise par le serveur en raison d'une syntaxe mal formée " - il ne doit donc pas être utilisé pour des erreurs de validation, à mon humble avis.
Martin Lie
@Vidya stackoverflow.com/questions/42851301/… jetez un oeil à cette erreur je suis également confronté au même problème similaire à cette erreur si vous savez s'il vous plaît aidez-moi
Mohan Gopi
74

Depuis w3.org

10.4.1 400 Mauvaise requête

La demande n'a pas pu être comprise par le serveur en raison d'une syntaxe incorrecte. Le client NE DEVRAIT PAS répéter la demande sans modifications.

Jason Sperske
la source
10
L'exactitude du renvoi d'une erreur 400 n'est pas basée sur un champ par rapport à une valeur mais sur la demande dans son ensemble. Je pense que HTTP 400 est une bonne façon de procéder
Jason Sperske
Voulez-vous dire qu'une réponse de 400 doit être utilisée pour dire aux clients que quelque chose, c'est-à-dire l'URL, les en-têtes, le corps, etc., dans la demande pourrait être faux et pas seulement le corps?
MasterJoe2
3
bien pour l'url, le code correct est 404, pour les en-têtes, je suppose que c'est un tirage au sort, 403 (interdit) semble être la bonne façon de procéder si les en-têtes rejettent l'identité, mais que se passe-t-il si les en-têtes déterminent le format de sortie? la seule voie qui me semble appropriée pour 400 se trouve dans la situation où une action est demandée qui n'a pas de sens et ne devrait pas être répétée. J'ai écrit cette réponse il y a 4 ans, ces jours-ci, je pense que même les erreurs devraient renvoyer 200, et que les erreurs ne devraient s'appliquer qu'à la transmission http et non à la charge utile.
Jason Sperske
1
Cette réponse couvre une grande partie de cela, même si je n'ai pas encore lu tous les graphiques stackoverflow.com/a/34324179/16959
Jason Sperske
Les équilibreurs de charge, proxys et autres middleware @JasonSperske utilisent souvent des codes d'état pour faciliter le routage, le rapport et la réparation. heureusement, les codes comme "422" concernent expressément la charge utile, donc il y a de la place dans la spécification pour les codes d'état de la charge utile.
Erik Aronesty
53

La sélection d'un code de réponse HTTP est une tâche assez simple et peut être décrite par des règles simples. La seule partie délicate qui est souvent oubliée est le paragraphe 6.5 de la RFC 7231:

Sauf lorsqu'il répond à une demande HEAD, le serveur DEVRAIT envoyer une représentation contenant une explication de la situation d'erreur, et s'il s'agit d'une condition temporaire ou permanente.

Les règles sont les suivantes:

  1. Si la demande a réussi, retournez le code 2xx (3xx pour la redirection). S'il y a eu une erreur de logique interne sur un serveur, retournez 5xx. S'il y a quelque chose de mal dans la demande du client, retournez le code 4xx.
  2. Consultez le code de réponse disponible dans la catégorie sélectionnée. Si l'un d'eux a un nom qui correspond bien à votre situation, vous pouvez l'utiliser. Sinon, il suffit de revenir au code x00 (200, 400, 500). En cas de doute, retournez au code x00.
  3. Renvoie la description de l'erreur dans le corps de la réponse. Pour les codes 4xx, il doit contenir suffisamment d'informations pour que le développeur client comprenne la raison et répare le client. Pour 5xx, pour des raisons de sécurité, aucun détail ne doit être révélé.
  4. Si le client doit distinguer différentes erreurs et avoir des réactions différentes selon lui, définissez un format d'erreur lisible et extensible par machine et utilisez-le partout dans votre API. C'est une bonne pratique de le faire dès le début.
  5. Gardez à l'esprit que le développeur client peut faire des choses étranges et essayer d'analyser les chaînes que vous renvoyez en tant que description lisible par l'homme. Et en changeant les chaînes, vous briserez ces clients mal écrits. Donc, fournissez toujours une description lisible par machine et essayez d'éviter de rapporter des informations supplémentaires dans le texte.

Donc, dans votre cas, j'ai renvoyé 400 erreurs et quelque chose comme ça si "Roman" est obtenu à partir de l'entrée utilisateur et le client doit avoir une réaction spécifique:

{
    "error_type" : "unsupported_resource",
    "error_description" : "\"Roman\" is not supported"
}

ou une erreur plus générique, si une telle situation est une mauvaise erreur logique dans un client et n'est pas attendue, sauf si le développeur a fait quelque chose de mal:

{
    "error_type" : "malformed_json",
    "error_description" : "\"Roman\" is not supported for \"requestedResource\" field"
}
Alexey Guseynov
la source
21

Dans aucun des cas, la "syntaxe n'est mal formée". Ce sont les sémantiques qui ont tort. Par conséquent, à mon humble avis, un 400 est inapproprié. Au lieu de cela, il serait approprié de renvoyer un 200 avec une sorte d'objet d'erreur tel que { "error": { "message": "Unknown request keyword" } }ou autre.

Considérez le (s) chemin (s) de traitement client. Une erreur de syntaxe (par exemple, un JSON invalide) est une erreur dans la logique du programme, en d'autres termes un bug quelconque, et doit être traitée en conséquence, d'une manière similaire à un 403, par exemple; en d'autres termes, quelque chose de mal a mal tourné.

Une erreur dans une valeur de paramètre, d'autre part, est une erreur de sémantique, peut-être due à une entrée utilisateur mal validée. Ce n'est pas une erreur HTTP (bien que je suppose que ce pourrait être un 422). Le chemin de traitement serait différent.

Par exemple, dans jQuery, je préférerais ne pas avoir à écrire un seul gestionnaire d'erreur qui traite à la fois des choses comme 500 et d'une erreur sémantique spécifique à l'application. D'autres frameworks, Ember pour un, traitent également les erreurs HTTP comme les 400 et 500 comme de grosses défaillances, obligeant le programmeur à détecter ce qui se passe et à se ramifier selon qu'il s'agit d'une "vraie" erreur ou non.


la source
4
+1, Le P dans HTTP signifie Protocole et si la réponse est une erreur HTTP, cela devrait être un problème de bas niveau. J'ai évité beaucoup de complexité de code au fil des ans en utilisant l'approche décrite par torazaburo. Il y aurait moins de douleur dans le pays REST si nous écrivions tous du code résilient au lieu de souffler si fréquemment avec des erreurs HTTP.
Dem Pilafian
25
200 signifie que la demande a été traitée, donc une logique de réussite normale doit être exécutée sur un client. Ici, nous avons définitivement une erreur, donc la réponse ne peut pas avoir de code 2xx ou 3xx. Il ne peut pas non plus s'agir de 5xx car il s'agit d'une erreur côté serveur et nous avons une erreur côté client. Cela doit donc être une erreur 4xx. Mais la description de l'erreur dans le corps de la réponse est une bonne chose à faire et est en fait un moyen conseillé par la spécification HTTP.
Alexey Guseynov
422, c'est mieux, pour les enregistreurs, les proxys et autres outils
Erik Aronesty
16

Utiliser des 400codes d'état à d'autres fins que d'indiquer que la demande est mal formée est tout simplement faux.

Si la charge utile de la demande contient une séquence d'octets qui n'a pas pu être analysée comme application/json(si le serveur attend ce format de données), le code d'état approprié est 415:

Le serveur refuse de traiter la demande car l'entité de la demande est dans un format non pris en charge par la ressource demandée pour la méthode demandée.

Si la charge utile de la demande est syntaxiquement correcte mais sémantiquement incorrecte, le 422code de réponse non standard peut être utilisé ou le 403code d'état standard :

Le serveur a compris la demande, mais refuse de la satisfaire. L'autorisation n'aidera pas et la demande NE DEVRAIT PAS être répétée.

Cochise Ruhulessin
la source
3
non, 415 est pour quand l'entité est revendiquée comme étant du mauvais type, par exemple image/gifau lieu d'être text/json dans l'en- Content-Type:tête. - vraisemblablement, cela s'applique également si un composant d'un multipartie a le mauvais type spécifié, voir tools.ietf.org/html/rfc4918 où il discute 422 pour plus de discussion,
Jasen
8

Pensez aux attentes.

En tant qu'application cliente, vous vous attendez à savoir si quelque chose ne va pas du côté serveur. Si le serveur doit renvoyer une erreur lorsqu'il blahest manquant ou si la requestedResourcevaleur est incorrecte, une erreur 400 serait appropriée.

film42
la source
5

En complément, pour ceux qui pourraient rencontrer le même problème que le mien, j'utilise $.ajaxpour publier des données de formulaire sur le serveur et j'ai également eu l' 400erreur au début.

Supposons que j'ai une variable javascript,

var formData = {
    "name":"Gearon",
    "hobby":"Be different"
    }; 

N'utilisez pas de variable formDatadirectement comme valeur de clé datacomme ci-dessous:

$.ajax({
    type: "post",
    dataType: "json",
    url: "http://localhost/user/add",
    contentType: "application/json",
    data: formData,
    success: function(data, textStatus){
        alert("Data: " + data + "\nStatus: " + status); 
    }
});

Utilisez plutôt JSON.stringify pour encapsuler les éléments formDataci-dessous:

$.ajax({
    type: "post",
    dataType: "json",
    url: "http://localhost/user/add",
    contentType: "application/json",
    data: JSON.stringify(formData),
    success: function(data, textStatus){
        alert("Data: " + data + "\nStatus: " + status); 
    }
});

Quoi qu'il en soit, comme d'autres l'ont illustré, l'erreur est due au fait que le serveur n'a pas pu reconnaître la requête provoquant une syntaxe mal formée, je soulève simplement une instance à l'entraînement. J'espère que cela serait utile à quelqu'un.

Eugène
la source
4

Vérifiez d'abord l'URL, elle peut être erronée, si elle est correcte, vérifiez le corps de la demande que vous envoyez, la cause possible est que la demande que vous envoyez manque la syntaxe correcte.

Pour élaborer, recherchez les caractères spéciaux dans la chaîne de requête. S'il est (caractère spécial) utilisé, c'est la cause principale de cette erreur.

essayez de copier la demande et d'analyser chaque donnée de balise.

Ankur Bhutani
la source
J'obtenais une erreur http 400, j'ai vérifié que ma demande avait des caractères spéciaux. Pour résoudre ce problème, j'ai passé le charset = UTF-8 dans le type de contenu.
Kislay Kishore