HTTPQUERY
Français

304 Not Modified

Utilisation

Le code de statut 304 Not Modified est envoyé lorsque la requête est sûre, comme une requête GET ou HEAD, et que le serveur détermine que la ressource n’a pas changé depuis la version stockée dans le cache du client. Cela économise de la bande passante, car le serveur ne retransmet pas des données que le client possède déjà.

Remarque

304 Not Modified n’est pas une redirection, bien qu’il partage la classe de statut 3xx. Les redirections (301, 302, 307, 308) envoient le client vers une autre URL via l’en-tête Location. 304 indique au client de réutiliser sa copie en cache de la même ressource, et aucun en-tête Location n’est envoyé. Les DevTools des navigateurs regroupent parfois 304 avec les redirections, ce qui ajoute à la confusion.

Remarque

« 200 (from disk cache) » dans les DevTools signifie que le navigateur a servi la ressource depuis le cache sans contacter le serveur, parce que le max-age de Cache-Control n’a pas expiré. 304 signifie que le navigateur a contacté le serveur pour revalider et que le serveur a confirmé que la copie en cache est à jour. Un 200 servi depuis le cache n’implique aucune requête réseau, tandis qu’un 304 implique un aller-retour.

Le serveur génère un ou plusieurs des en-têtes suivants dans sa réponse :

Comme l’objectif de la réponse 304 Not Modified est de minimiser la bande passante, le serveur omet les en-têtes non inclus dans la requête d’origine, sauf s’ils facilitent le processus de mise à jour du cache.

Pour les requêtes GET conditionnelles, les directives pertinentes sont If-None-Match et If-Modified-Since. Elles s’appuient sur un validateur tel qu’un ETag pour déterminer si la ressource doit être retransmise.

Exemple

Le client demande une ressource, reçoit un ETag identifiant la version, puis revalide plus tard. Le serveur constate que la ressource est inchangée et renvoie 304 Not Modified. À la troisième requête, une nouvelle version est disponible et une réponse 200 complète est envoyée avec un ETag mis à jour.

Remarque

Chaque fois que le serveur met à jour une ressource, un nouvel ETag est généré. En alternative, le serveur renvoie une date Last-Modified et le client utilise If-Modified-Since à la place, ce qui évite au serveur d’avoir à conserver un historique des ETag.

Impact SEO

Lorsque Googlebot reçoit un 304, le crawler constate que le contenu n’a pas changé depuis le dernier passage. Le pipeline d’indexation recalcule les signaux de classement pour l’URL, mais ne récupère ni ne réindexe le contenu.

Le piège du 304 périmé

Un 304 confirme que la version en cache est toujours à jour. Si le serveur a précédemment servi une page défectueuse (corps vide, contenu d’erreur) avec un 200 et que le crawler a mis le résultat en cache, un 304 ultérieur indique au crawler que la version défectueuse persiste. Le crawler cesse de revérifier, puisque le « contenu » n’a pas changé. Corriger la page ne suffit pas. Le serveur doit renvoyer un nouveau 200 avec le corps corrigé (et un nouvel ETag) pour remplacer l’erreur mise en cache. Ce scénario est difficile à déboguer, car la cause racine (une erreur transitoire passée) n’est plus visible.

Requête initiale

GET /news.html HTTP/1.1
Host: example.com

Réponse initiale

HTTP/1.1 200 OK
ETag: "1234000"
Content-Type: text/html
Content-Length: 1250

<message body contains requested resource>

Deuxième requête

GET /news.html HTTP/1.1
Host: example.com
If-None-Match: "1234000"

Deuxième réponse

HTTP/1.1 304 Not Modified
ETag: "1234000"

Troisième requête

GET /news.html HTTP/1.1
Host: example.com
If-None-Match: "1234000"

Troisième réponse

HTTP/1.1 200 OK
ETag: "1234001"
Content-Type: text/html
Content-Length: 1600

<message body contains requested resource>

Références de code

.NET

HttpStatusCode.NotModified

Rust

http::StatusCode::NOT_MODIFIED

Rails

:not_modified

Go

http.StatusNotModified

Symfony

Response::HTTP_NOT_MODIFIED

Python3.5+

http.HTTPStatus.NOT_MODIFIED

Java

java.net.HttpURLConnection.HTTP_NOT_MODIFIED

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_NOT_MODIFIED

Angular

@angular/common/http/HttpStatusCode.NotModified