Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
Proposition d'amélioration du mecanisme du cache
#1
Bonjour,
Actuellement le code du routeur S3 ne défini pas de politique pour le cache, c'est donc le navigateur qui décide de cacher ou non comme bon lui semble.

Avec le routeur classique on a constaté que très souvent après un changement de version, on rencontrait des bugs temporaires que l'on corrigeait via des Ctrl + F5.
Afin d’améliorer cette situation pour le routeur S3, je propose de déclarer explicitement la politique pour le cache. Pour toutes les requêtes dynamiques il faut que le cache soit désactivé et pour les requêtes statiques il faut que le cache soit actif et que celui ci ne soit pas mis à jour tant que la version du routeur n'a pas changé.

Pour effectuer cela, je propose d'utiliser le header HTTP ETag (https://www.geeksforgeeks.org/computer-n...http-etag/). En utilisant le numéro de version (combiné à la date de compilation) comme ETag cela permet d'indiquer au navigateur que la ressource peut être lue depuis le cache tant que la version du routeur n'a pas changé.

Cela devrait améliorer globalement les performances de l'interface web car les ressources statiques seraient cachées. Un autre avantage est que cela limitera fortement, voir supprimera, le besoin de faire des Ctrl+F5 à chaque changement de version.

J'ai effectué ces changements en local et cela semble bien fonctionner.
Concrètement, dans Server.cpp j'ai ajouté la declaration de l'ETAG ainsi que la fonction à utiliser pour effectuer les requêtes statiques :
Code :
// Envoi d'une ressource statique embarquée avec cache navigateur : ETag + revalidation (304 si inchangé).
// L'ETag change à chaque compilation de ce fichier (donc à chaque modification des ressources web).
// "no-cache" = le navigateur garde le fichier mais revalide à chaque fois : pas de JS périmé après une mise à jour OTA.
static const char ETAG_RESSOURCES[] = "\"" PROG_VERSION " " __DATE__ " " __TIME__ "\"";

static void sendEmbeddedCached(AsyncWebServerRequest *request, const char *type, const char *content)
{
  AsyncWebServerResponse *response;
  if (request->hasHeader("If-None-Match") && request->header("If-None-Match").indexOf(ETAG_RESSOURCES) >= 0)
  {
    response = request->beginResponse(304); // Non modifié : pas de corps
  }
  else
  {
    response = request->beginResponse(200, type, (const uint8_t *)content, strlen(content));
  }
  response->addHeader("ETag", ETAG_RESSOURCES);
  response->addHeader("Cache-Control", "no-cache");
  request->send(response);
}

Il faut également désactiver le cache par défaut avec :
Code :
  DefaultHeaders::Instance().addHeader("Cache-Control", "no-store");

Ensuite pour chaque ressource statique que l'on veut cacher il faut utiliser sendEmbeddedCached au lieu de request->send, par exemple : 
Code :
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { sendEmbeddedCached(request, "text/html", pageHtmlHome); });
  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request) { sendEmbeddedCached(request, "image/svg+xml", Favicon); });

J'ai effectué ce changement pour pageHtmlHome, Favicon, HomeCSS, JS_carteGraphEnergie, JS_Home, JS_carteGraphEnsoleillement, JS_carteGraphHistorique, JS_carteJauge, JS_carteTableauOuvertures, JS_carteTableauPuissance, pageHtmlBrute, JS_Brute, JS_Para, JS_Action, JS_boolean, JS_paraBloc, CommunCSS et JS_Commun.

J'ai attaché à ce message le fichier Server.cpp de la beta 15 modifié.
Qu'en pensez vous ?


Pièces jointes
.txt   Server.cpp.txt (Taille : 33.34 Ko / Téléchargements : 3)
Répondre

#2
(Il y a 3 heures)Mike a écrit : Bonjour,
Actuellement le code du routeur S3 ne défini pas de politique pour le cache, c'est donc le navigateur qui décide de cacher ou non comme bon lui semble.

Avec le routeur classique on a constaté que très souvent après un changement de version, on rencontrait des bugs temporaires que l'on corrigeait via des Ctrl + F5.
Afin d’améliorer cette situation pour le routeur S3, je propose de déclarer explicitement la politique pour le cache. Pour toutes les requêtes dynamiques il faut que le cache soit désactivé et pour les requêtes statiques il faut que le cache soit actif et que celui ci ne soit pas mis à jour tant que la version du routeur n'a pas changé.

Pour effectuer cela, je propose d'utiliser le header HTTP ETag (https://www.geeksforgeeks.org/computer-n...http-etag/). En utilisant le numéro de version (combiné à la date de compilation) comme ETag cela permet d'indiquer au navigateur que la ressource peut être lue depuis le cache tant que la version du routeur n'a pas changé.

Cela devrait améliorer globalement les performances de l'interface web car les ressources statiques seraient cachées. Un autre avantage est que cela limitera fortement, voir supprimera, le besoin de faire des Ctrl+F5 à chaque changement de version.

J'ai effectué ces changements en local et cela semble bien fonctionner.
Concrètement, dans Server.cpp j'ai ajouté la declaration de l'ETAG ainsi que la fonction à utiliser pour effectuer les requêtes statiques :
Code :
// Envoi d'une ressource statique embarquée avec cache navigateur : ETag + revalidation (304 si inchangé).
// L'ETag change à chaque compilation de ce fichier (donc à chaque modification des ressources web).
// "no-cache" = le navigateur garde le fichier mais revalide à chaque fois : pas de JS périmé après une mise à jour OTA.
static const char ETAG_RESSOURCES[] = "\"" PROG_VERSION " " __DATE__ " " __TIME__ "\"";

static void sendEmbeddedCached(AsyncWebServerRequest *request, const char *type, const char *content)
{
  AsyncWebServerResponse *response;
  if (request->hasHeader("If-None-Match") && request->header("If-None-Match").indexOf(ETAG_RESSOURCES) >= 0)
  {
    response = request->beginResponse(304); // Non modifié : pas de corps
  }
  else
  {
    response = request->beginResponse(200, type, (const uint8_t *)content, strlen(content));
  }
  response->addHeader("ETag", ETAG_RESSOURCES);
  response->addHeader("Cache-Control", "no-cache");
  request->send(response);
}

Il faut également désactiver le cache par défaut avec :
Code :
  DefaultHeaders::Instance().addHeader("Cache-Control", "no-store");

Ensuite pour chaque ressource statique que l'on veut cacher il faut utiliser sendEmbeddedCached au lieu de request->send, par exemple : 
Code :
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { sendEmbeddedCached(request, "text/html", pageHtmlHome); });
  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request) { sendEmbeddedCached(request, "image/svg+xml", Favicon); });

J'ai effectué ce changement pour pageHtmlHome, Favicon, HomeCSS, JS_carteGraphEnergie, JS_Home, JS_carteGraphEnsoleillement, JS_carteGraphHistorique, JS_carteJauge, JS_carteTableauOuvertures, JS_carteTableauPuissance, pageHtmlBrute, JS_Brute, JS_Para, JS_Action, JS_boolean, JS_paraBloc, CommunCSS et JS_Commun.

J'ai attaché à ce message le fichier Server.cpp de la beta 15 modifié.
Qu'en pensez vous ?

Merci pour cette évolution du code. Je l'ai mise dans la version beta.16. Il est vrai que le cache a généré plein de questions sur le forum.On va tester.

Cordialement

André
Répondre



Atteindre :


Utilisateur(s) parcourant ce sujet :
2 visiteur(s)

Moteur MyBB, © 2002-2026 Melroy van den Berg.