HTTPQUERY
Français

412 Precondition Failed

Utilisation

Lorsque le message d’erreur 412 Precondition Failed est reçu, le client sait qu’une ou plusieurs conditions spécifiées dans la requête n’ont pas été satisfaites et que la ressource n’était pas dans l’état attendu. Le comportement précis dépend de l’en-tête de précondition. Un échec de If-Match renvoie 412 pour n’importe quelle méthode. Un échec de If-None-Match renvoie 304 pour GET et HEAD, et 412 pour toutes les autres méthodes.

Cela ressemble au 304, à ceci près que dans le cas du 304 la ressource n’a pas été envoyée parce que le client disposait déjà de la version la plus récente, rendant une nouvelle transmission inutile.

Impact SEO

Les moteurs de recherche comme Google n’indexent pas une URL dont la réponse porte le statut 412. Les URL précédemment indexées sont retirées des résultats de recherche.

Exemple

Le client souhaite répondre à un billet de blog, mais uniquement à condition que le billet n’ait pas changé depuis la dernière consultation de la ressource par le client. La condition est portée par l’en-tête If-Unmodified-Since. Lorsque la condition échoue, la ressource a été modifiée et le serveur répond 412 Precondition Failed pour indiquer que la requête n’a pas été exécutée.

En suivant ce protocole, le problème de la « mise à jour perdue » est évité. Les mises à jour perdues surviennent lorsque plusieurs clients écrivent sur la même ressource et qu’un ou plusieurs d’entre eux travaillent sur une version obsolète. En s’assurant que la ressource n’a pas été modifiée, on empêche l’écrasement des données modifiées entre-temps.

Requête

POST /blog/update?postid=111&task=reply HTTP/1.1
Host: example.com
If-Unmodified-Since: Fri, 1 Jan 2021 00:00:00 GMT
Content-Type: text/plain
Content-Length: 45

<Message body contains reply-text from the client>

Réponse

HTTP/1.1 412 Precondition Failed
Content-Type: text/html
Content-Length: 139

<html>
  <head>
    <title>Blog Update Error</title>
  </head>
  <body>
   <p>The post has changed since last viewed.</p>
  </body>
</html>

Comment corriger

Récupérez la version actuelle de la ressource avec une requête GET ou HEAD afin d’obtenir la valeur ETag ou Last-Modified la plus récente. Remplacez le validateur périmé dans l’en-tête If-Match ou If-Unmodified-Since par la valeur actuelle, puis réessayez la requête.

Lors de l’utilisation d’un contrôle de concurrence optimiste (courant dans les API REST et les plateformes CMS), le déroulement est le suivant :

Vider le cache du navigateur résout les erreurs 412 causées par des validateurs mis en cache périmés. Le navigateur conserve un ETag ou un horodatage obsolète et attache automatiquement d’anciens en-têtes conditionnels aux requêtes.

Les proxys de cache et les CDN situés entre le client et le serveur d’origine servent parfois des validateurs périmés. Vérifiez que les configurations de proxy transmettent les en-têtes conditionnels sans les modifier. AWS CloudFront, par exemple, renvoie 412 lorsqu’un en-tête If-Match sur une requête GET ne correspond pas à l’ETag de l’objet. Dans ces cas-là, confirmez que le cache du CDN est frais ou invalidez la distribution.

412 face à 409

412 et 409 indiquent tous deux un conflit d’état, mais la cause diffère. Une réponse 412 signifie qu’un en-tête de précondition (If-Match ou If-Unmodified-Since) a été évalué à faux. Une réponse 409 signifie que la requête entre en conflit avec l’état actuel de la ressource, indépendamment des en-têtes conditionnels. Utilisez 412 pour les contrôles de concurrence optimiste pilotés par des ETag ou des horodatages. Utilisez 409 pour les conflits de logique métier, tels que les entrées en double ou les transitions d’état invalides.

Références de code

.NET

HttpStatusCode.PreconditionFailed

Rust

http::StatusCode::PRECONDITION_FAILED

Rails

:precondition_failed

Go

http.StatusPreconditionFailed

Symfony

Response::HTTP_PRECONDITION_FAILED

Python3.5+

http.HTTPStatus.PRECONDITION_FAILED

Java

java.net.HttpURLConnection.HTTP_PRECON_FAILED

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_PRECONDITION_FAILED

Angular

@angular/common/http/HttpStatusCode.PreconditionFailed