La naissance des cookies
Étant donné que le protocole HTTP est sans état, les services côté serveur doivent être avec état. Le but initial de la naissance des cookies était de stocker les informations d'état sur le Web pour une utilisation facile du côté serveur. Par exemple, déterminez si l'utilisateur visite le site Web pour la première fois. La dernière spécification est RFC 6265, qui est une spécification implémentée par les serveurs de navigateur.
Le traitement des cookies est divisé en:
Le serveur envoie des cookies comme le client
Le navigateur enregistre les cookies
Après cela, chaque fois que la demande HTTP est demandée, le navigateur enverra le cookie au serveur.
Envoyer et analyser le côté serveur
Envoyer des cookies
Les cookies côté serveur envoyés par le client sont implémentés via des paquets de réponse HTTP. Dans Set Cookies, les cookies qui doivent être envoyés par le client sont définis. Le format cookie est le suivant:
Set-cookie: "name = valeur; domain = .domain.com; path = /; expires = sat, 11 juin 2016 11:29:42 gmt; httponly; sécurisé"
Où name = valeur est une option requise, et d'autres sont facultatifs. Les principales composantes des cookies sont les suivantes:
Nom: Un nom de cookie unique et définitif. D'une manière générale, le nom d'un cookie est insensible à la casse.
Valeur: la valeur de chaîne stockée dans le cookie. Il est préférable de coder URL le nom et la valeur du cookie
Domaine: le cookie est valable pour quel domaine. Toutes les demandes envoyées à ce domaine contiendront ces informations sur les cookies. Cette valeur peut contenir des sous-domaines (tels que:
yq.aliyun.com) ou il ne peut pas être inclus (par exemple: .aliyun.com, il est valable pour tous les sous-domaines d'Aliyun.com).
Chemin: indique le chemin affecté par ce cookie. Le navigateur enverra des cookies en fonction de cette configuration, tels que la correspondance de chemin dans le domaine spécifié.
Expire: temps d'expiration, horodatage indiquant quand le cookie doit être supprimé (c'est-à-dire quand le cookie doit être arrêté à l'envoi du serveur). Si vous ne définissez pas cet horodatage, le navigateur supprimera tous les cookies lorsque la page sera fermée; Cependant, vous pouvez également définir le temps de suppression vous-même. Cette valeur est dans le format de temps GMT. Si le temps client et serveur est incohérent, il y aura des écarts lors de l'utilisation expire.
MAX-AGE: La même fonction que l'expiration est utilisée pour dire au navigateur combien de temps ce cookie expire (en secondes), plutôt qu'un point de temps fixe. Dans des circonstances normales, l'âge maximum a une priorité plus élevée que l'expiration.
Httponly: informe le navigateur de ne pas autoriser le document de script.cookie de modifier cette valeur, et cette valeur n'est pas non plus visible dans document.cookie. Mais ce cookie sera toujours transporté sur la demande HTTP. Notez que bien que cette valeur ne soit pas disponible dans le script, elle existe toujours dans le répertoire d'installation du navigateur en tant que fichier. Ce paramètre est généralement défini côté serveur.
Secure: Indicateur de sécurité, après avoir spécifié, il ne peut être envoyé au serveur que lors de l'utilisation du lien SSL. S'il s'agit d'un lien HTTP, ces informations ne seront pas transmises. Même si l'attribut sécurisé est défini, cela ne signifie pas que d'autres ne peuvent pas voir les informations sur les cookies enregistrées localement sur votre machine, alors ne mettez pas d'informations importantes dans les cookies et ne les définissez pas directement du serveur.
Des exemples de cookies sont les suivants:
var http = require ('http'); var fs = require ('fs'); http.createServer (function (req, res) {res.sethEader ('status', '200 ok'); res.sethEader ('set-cookie', 'isvisit = true; domain = .yourDomain.com; path = /; max-age = 1000') ;wwrite. World '); res.end ();}). Écouter (8888); console.log (' Running LocalHost: 8888 ')Le réglage set-cookie directement est trop original. Nous pouvons encapsuler le processus de réglage des cookies comme suit:
var Selilize = function (name, val, options) {if (! name) {throw new error ("cooleie doit avoir le nom"); } var enc = EncodeuRIComponent; var parties = []; val = (val! == null && val! == Undefined)? val.toString (): ""; Options = Options || {}; Parts.push (enc (name) + "=" + Enc (Val)); // il doit y avoir deux points dans le domaine if (options.domain) {part.push ("domain =" + options.domain); } if (options.path) {part.push ("path =" + options.path); } // Si vous ne définissez pas Expires et que les navigateurs max-âge effaceront les cookies lorsque la page est fermée if (options.expires) {part.push ("expires =" + options.expires.togmtString ()); } if (options.Maxage && typeof options.maxage === "nombre") {part.push ("max-age =" + options.maxage); } if (options.httponly) {part.push ("httponly"); } if (options.secure) {part.push ("sécurisé"); } return partie.join (";");}Il convient de noter que si un cookie est défini sur un temps passé, le navigateur supprimera immédiatement le cookie; De plus, l'élément de domaine doit avoir deux points, il ne peut donc pas être défini sur localhost:
Quelque chose qui n'a pas été clairement indiqué pour moi ici et qui m'a totalement confondu pendant un certain temps, c'est que les noms de domaine doivent contenir au moins deux points (.), Par conséquent, «localhost» est invalide et que le navigateur refusera de régler le cookie!
Cookies d'analyse côté serveur
Les cookies peuvent définir différents domaines et chemins, donc pour la même valeur de nom, il peut être répété sous différents chemins dans différents domaines et différents chemins. Le navigateur triera la commande dans l'ordre qui correspond le mieux à l'URL ou à l'adresse de page demandée actuelle.
Ainsi, lorsque le cookie est passé du côté serveur du côté actuel a plusieurs valeurs de nom en double, nous n'avons besoin que de celui qui correspond le plus, c'est-à-dire le premier. Le code d'analyse côté serveur est le suivant:
var parse = function (cstr) {if (! cstr) {return null; } var dec = decodeuriComponent; var cookies = {}; var parties = cstr.split (// s *; / s * / g); Parties.ForEach (fonction (p) {var pos = p.indexof ('='); // nom et la valeur doivent être codés avant que le cookie ne soit stocké var name = pos> -1? dec (p.substr (0, pos)): p; var val = pos> -1? dec (p.substr (pos + 1)): null; // vous seul avez besoin de le plus correspondant si (! cookies [name] = val;} / * else if (! cookies [name] de l'arrivée) {cookies [name] = [cookies [name]. retourner les cookies;}Accès au client
Le navigateur gère les cookies passés en arrière-plan et permet aux développeurs d'utiliser Document.Cookies en JavaScript pour accéder aux cookies. Mais cette interface est très boiteuse à utiliser. Il montrera différents comportements en raison des différentes façons dont il est utilisé.
Lorsqu'il est utilisé pour obtenir des valeurs d'attribut, Document.cookie renvoie toutes les chaînes disponibles sur la page actuelle (en fonction du domaine du cookie, du chemin, du temps d'expiration et des paramètres de sécurité). Le format de la chaîne est le suivant:
"name1 = value1; name2 = value2; name3 = value3";
Lorsqu'il est utilisé pour définir des valeurs, la propriété document.cookie peut être définie sur une nouvelle chaîne de cookie. Cette chaîne est interprétée et ajoutée à la collection de cookies existante. comme:
document.cookie = "_fa = aaaffffasdsf; domain = .dojotoolkit.org; path = /"
Définition Document.Cookie ne remplace pas les cookies à moins que le chemin de domaine de valeur de nom de jeu soit répété avec un cookie existant.
Comme il est très gênant de lire et d'écrire des cookies, nous pouvons encapsuler certaines fonctions pour gérer les cookies, principalement pour l'addition, la modification et la suppression des cookies.
var cookieutils = {get: function (name) {var cookiename = encodeuRIComponent (name) + "="; // n'obtiens que le nom le plus correspondant, valeur var cookiestart = document.cookie.indexof (Cookiename); VAR CookieValue = NULL; if (Cookiestart> -1) {// de Cookiestart var cookieend = document.cookie.indexof (';', Cookiestart); // de = after = (cookieend> -1) {Cookievalue = decodeuriComponent (document.cookie.substring (Cookiestart + Cookiename.length, cookieend)); } else {Cookievalue = decodeuriComponent (document.cookie.substring (Cookiestart + Cookiename.length, document.cookie.length)); }} return Cookievalue; }, set: function (name, val, options) {if (! name) {throw new error ("cooliie doit avoir le nom"); } var enc = EncodeuRIComponent; var parties = []; val = (val! == null && val! == Undefined)? val.toString (): ""; Options = Options || {}; Parts.push (enc (name) + "=" + Enc (Val)); // Le domaine doit contenir deux points if (options.domain) {part.push ("domain =" + options.domain); } if (options.path) {part.push ("path =" + options.path); } // Si vous ne définissez pas Expires et que le navigateur max-âge effacera les cookies lorsque la page est fermée if (options.expires) {part.push ("expires =" + options.path); } // Si vous ne définissez pas Expires et que le navigateur max-âge effacera les cookies lorsque la page est fermée if (options.expires) {part.push ("expires =" + options.expires.togmtString ()); } if (options.Maxage && typeof options.maxage === "nombre") {part.push ("max-age =" + options.maxage); } if (options.httponly) {part.push ("httponly"); } if (options.secure) {part.push ("sécurisé"); } document.cookie = part.join (";"); }, delete: function (nom, options) {options.expires = new Date (0); // défini sur la date passée this.set (nom, null, options); }}Avantages de la mise en cache
Le cache Web communément appelé référence à un périphérique HTTP qui peut enregistrer automatiquement des copies des demandes HTTP courantes. Pour les développeurs frontaux, les navigateurs jouent un rôle important. De plus, il existe différents serveurs proxy communs qui peuvent également être utilisés pour la mise en cache. Lorsqu'une demande Web atteint le cache, le cache extrait la réplique du contenu de la réplique locale sans passer par le serveur. Cela apporte les avantages suivants:
La mise en cache réduit la transmission des données redondantes et économise le trafic
Cache atténue les problèmes d'étranglement de la bande passante. Les pages peuvent être chargées plus rapidement sans plus de bande passante
Le cache atténue la congestion instantanée et réduit les exigences du serveur d'origine.
Le cache réduit le délai de distance car les pages de chargement des endroits les plus éloignées seront plus lentes.
Type de cache
Le cache peut être dédié à un seul utilisateur ou partagé par plusieurs utilisateurs. Un cache dédié est appelé un cache privé, et un cache partagé est appelé un cache public.
Cache privé
Le cache privé est uniquement pour les utilisateurs propriétaires, il ne nécessite donc pas beaucoup d'espace et est bon marché. Les navigateurs Web ont des caches privés intégrés - la plupart des navigateurs mettront en cache des ressources communes sur le disque et la mémoire de votre PC. Par exemple, l'emplacement de stockage du cache du navigateur Chrome est: c: / utilisateurs / your_account / appdata / local / google / chrome / utilisateur / user / par défaut.
Cache public
Les caches publiques sont des serveurs proxy partagés spéciaux, appelés serveurs de proxy de cache ou caches proxy (un but de proxy inversé). Le cache public acceptera l'accès de plusieurs utilisateurs, il peut donc mieux réduire le trafic redondant.
Dans la figure ci-dessous, chaque client accède à plusieurs reprises à une ressource au serveur (il n'est pas dans le cache privé pour le moment), de sorte qu'il accédera au serveur plusieurs fois, augmentant la pression sur le serveur. Lorsque vous utilisez un cache public partagé, le cache ne doit être récupéré du serveur et n'a pas à passer par le serveur à l'avenir, ce qui peut réduire considérablement la pression sur le serveur.
En fait, le cache public hiérarchique est généralement utilisé dans les applications réelles. L'idée de base est d'utiliser des caches petites et bon marché près du client, tandis qu'à un niveau supérieur, les caches plus grandes et plus puissantes sont progressivement adoptées pour charger des ressources partagées par plusieurs utilisateurs.
Flux de traitement du cache
Pour les développeurs frontaux, nous traitons principalement des caches dans le navigateur, le processus ci-dessus est donc simplifié à:
L'image suivante montre les résultats de la demande d'un site Web pour différentes ressources. On peut voir que certaines ressources sont lues directement à partir du cache, certaines ressources sont véhiculées avec le serveur et certaines ressources sont réinstallées à partir du serveur.
Notez que toutes les questions dont nous avons discuté sur les ressources de Cache sont uniquement pour les demandes de GET. Pour les opérations comportementales telles que Post, Supprimer et Put, il n'y a généralement pas de cache.
Limite de fraîcheur
HTTP conserve une copie de la ressource du serveur pendant une période de temps via Cache, qui est appelée limite de fraîcheur. Cela demande la même ressource pendant une période de temps et ne passera plus le serveur. Le contrôle du cache et expire dans le protocole HTTP peut être utilisé pour fixer la limite de la fraîcheur. Le premier est le nouvel en-tête de réponse ajouté dans HTTP1.1, et le second est l'en-tête de réponse dans HTTP1.0. Les deux font la même chose, mais comme Cache-Control utilise un temps relatif et expire peut avoir un problème que le temps client et serveur est différent, nous préférons le contrôle du cache.
Contrôle du cache
Jetons un coup d'œil à ce que les valeurs d'attribut peuvent être définies par Cache-Control:
L'âge maximum (l'unité est s) spécifie le temps valide maximal pour régler le cache, qui définit la durée. Lorsque le navigateur envoie une demande au serveur, le navigateur n'enverra plus de demande au serveur pendant l'âge maximum.
<html> <éad- head> <méta http-equiv = "contenu-type" contenu = "text / html; charset = utf-8"> <meta name = "Viewport" contenu = "width = device-width, initial-scale = 1.0, maximum-scale = 1.0, utilisable-compatable = no" /> <méta http-equiv = "x-compatable" Content = "ie = edge" /> <ititle> web cache </ title> <link rel = "raccourci icon" href = "./ shortcut.png"> <cript> </script> </ad> <body> <img src = "./ cache.png"> </htmot require ('fs'); http.createServer (function (req, res) {if (req.url === '/' || req.url === '' || req.url === '/index.html') {fs.readfile ('./ index.html', fonction (err, fichier) {console.Log (re.ur.url) / set Cache pour le document principal, Res.SethEader (Cache-Control ', "Non-cache, max-age =" + 5); fs.readfile ('./ cache.png', fonction (err, fichier) {res.sethEader ('cache-control', "max-age =" + 5); // cache cinq secondes res.setheader ('contenu-type', 'images / png'); res.writehead ('200', "non modifié"); res.end (file);}); }). Écouter (8888)Lorsque la page est accessible pour la deuxième fois dans les 5 secondes, le navigateur obtiendra directement des ressources du cache
Le public spécifie que la réponse peut être mise en cache dans le cache proxy et peut donc être partagée par plusieurs utilisateurs. Si privé n'est pas spécifié explicitement, il est par défaut public.
La réponse privée ne peut être mise en cache que dans le cache privé et ne peut pas être placée sur le cache proxy. Les ressources sensibles à certaines informations utilisateur doivent généralement être définies sur privé.
Le non-cache signifie que vous devez d'abord confirmer avec le serveur si la ressource a été modifiée (en vous appuyant sur If-None-Match et ETAG) avant de décider s'il faut utiliser le cache local.
Si le traitement ci-dessus de Cache.png est modifié à ce qui suit, chaque fois que vous visitez la page, le navigateur doit aller sur le serveur pour vérifier si la ressource a été modifiée.
fs.readfile ('./ cache.png', fonction (err, fichier) {console.log (req.heders); console.log (req.url) if (! req.heders ['if-none-match']) {res.setheader ('cache-control', "no-cache, max-age =" + 5); res. 'Images / Png'); Res.SethEader ('Cache-Control', "Max-Age =" + 5);Aucun magasin n'interdit absolument le cache de toute ressource, ce qui signifie que chaque fois que l'utilisateur demande la ressource, une demande sera envoyée au serveur et que la ressource complète sera téléchargée à chaque fois. Généralement utilisé pour les ressources confidentielles.
En ce qui concerne l'utilisation du contrôle du cache, voir l'image ci-dessous (à partir de grandes quantités)
Limite de fraîcheur du client
Cache-Control peut non seulement être défini dans l'en-tête de réponse, mais aussi dans l'en-tête de demande. Le navigateur peut décider de lire les ressources du cache en définissant le contrôle du cache dans l'en-tête de demande. C'est aussi pourquoi cliquer parfois sur le bouton Rafraîchissement du navigateur et entrer dans la barre d'adresse pour voir des résultats complètement différents dans le module réseau
Expire
Expire n'est pas recommandé, il spécifie une date d'expiration spécifique plutôt qu'un certain nombre de secondes. Étant donné que de nombreux serveurs et clients ont une horloge incohérente, il est préférable d'utiliser le contrôle du cache.
Vérification du serveur
La ressource mise en cache dans le navigateur ou le cache proxy expire ne signifie pas qu'elle est en fait différente des ressources du serveur d'origine, mais signifie seulement qu'il est temps de vérifier. Cette situation est appelée révification du serveur.
Si la ressource change, vous devez obtenir de nouvelles ressources et remplacer les anciennes ressources du cache.
Si la ressource n'a pas changé, le cache n'a besoin que d'obtenir un nouvel en-tête de réponse et un nouveau temps d'expiration pour mettre à jour le temps d'expiration de la ressource dans le cache.
La méthode de vérification recommandée pour HTTP1.1 est si-none-match / etag, et si-modifié-Since / Last-modifié est utilisée dans HTTP1.0.
ETAG et IF-None-Match
Générez une chaîne de hachage en fonction du contenu de l'entité, en identifiant l'état de la ressource et est généré par le serveur. Le navigateur transmettra cette chaîne au serveur pour vérifier que la ressource a été modifiée. S'il n'a pas été modifié, le processus est le suivant (l'image vient d'une brève discussion sur le cache Web):
Dans la démo ci-dessus, nous avons vu comment vérifier ETAG sur le serveur:
Puisque ETAG a une structure de serveur, l'unicité de ETAG doit être assurée dans l'environnement de cluster
Si-modifié-pseudo vs dernier modifié
Ces deux sont des en-têtes de demande / réponse utilisés dans HTTP 1.0 pour vérifier si la ressource a expiré. Ces deux en-têtes sont des dates. Le processus de vérification est similaire à ETAG, nous ne les présenterons donc pas en détail ici. Lorsque vous utilisez ces deux en-têtes pour vérifier que la ressource est mise à jour, les problèmes suivants existent:
Certaines ressources de document sont réécrites périodiquement, mais le contenu réel n'a pas changé. À l'heure actuelle, les métadonnées du fichier montrent que la date de modification la plus récente du fichier est différente de la façon dont-modifié-médifiée, ce qui entraîne des réponses inutiles.
Certaines ressources de document ont été modifiées, mais le contenu de la modification n'est pas important, et tous les caches ne sont pas tenus de mettre à jour (comme les commentaires de code)
En ce qui concerne la mise à jour de Cache, veuillez consulter la réponse de Zhang Yunlong ici. Cet article ne sera pas élargi en détail.
Le code de démonstration de cet article est le suivant:
<! Doctype html> <html> <éadf> <meta http-equiv = "contenu-type" contenu = "text / html; charset = utf-8"> <meta name = "wipport" contenu = "width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable = no" / meta = http-equiv = "x-ua-compatible" contenu = "ie = edge" /> <tight> web cache </title> <link rel = "raccourci icon" href = "./ shortcut.png"> </ script> </ script> </ head> <body> <img src = ". cache.png"> </gody> require ('http'); var fs = require ('fs'); http.createServer (fonction (req, res) {if (req.url === '/' || req.url === '' || req.url === '/index.html') Console.log (req.url) // Set Cache pour le document principal, sans effet. = univers '/cache.png') {fs.readfile ('./ cache.png', function (err, file) {console.log (req.heders); console.log (req.url) if (! req.heders [if-none-patch ']) {res.setheDer (' Cache-Control ', "max-eage =" + 5); Res.SethEader ('Content-Type', 'Images / Png'); res.end ();} else {res.setheader («Cache-Control», »,« Images / png » }}). Écouter (8888)Ok, l'introduction de cet article aux cookies se termine ici, j'espère que tout le monde l'aime.