O nascimento dos biscoitos
Como o protocolo HTTP está sem estado, os serviços do lado do servidor devem estar com estado. O objetivo original do nascimento dos cookies era armazenar informações de status na web para facilitar o uso no lado do servidor. Por exemplo, determine se o usuário está visitando o site pela primeira vez. A especificação mais recente é o RFC 6265, que é uma especificação implementada pelos servidores do navegador.
O processamento de cookies é dividido em:
O servidor envia cookies como o cliente
O navegador salva cookies
Depois disso, toda vez que a solicitação HTTP é solicitada, o navegador enviará o cookie para o servidor.
Enviar e analisar no lado do servidor
Envie cookies
Os cookies do lado do servidor enviados pelo cliente são implementados por meio de pacotes de resposta HTTP. Em cookies, os cookies que precisam ser enviados pelo cliente estão definidos. O formato de cookie é o seguinte:
Set-cookie: "name = value; domain = .domain.com; path =/; expire = SAT, 11 de junho de 2016 11:29:42 gmt; httponly; seguro"
Onde nome = valor é uma opção necessária e outros são opcionais. Os principais componentes dos cookies são os seguintes:
Nome: Um nome de cookie único e definido. De um modo geral, o nome de um cookie é insensível a maiúsculas.
Valor: o valor da string armazenado no cookie. É melhor URL codificando o nome e o valor do cookie
Domínio: Cookie é válido para qual domínio. Todas as solicitações enviadas a este domínio conterão essas informações de cookie. Este valor pode conter subdomínios (como:
yq.aliyun.com) ou não pode ser incluído (por exemplo: .aliyun.com, é válido para todos os subdomínios do Aliyun.com).
Caminho: indica o caminho afetado por este cookie. O navegador enviará cookies com base nessa configuração, como o caminho que corresponde ao domínio especificado.
Expira: Tempo de expiração, registro de data e hora indicando quando o cookie deve ser excluído (ou seja, quando o cookie deve parar de enviar para o servidor). Se você não definir esse registro de data e hora, o navegador excluirá todos os cookies quando a página estiver fechada; No entanto, você também pode definir o tempo de exclusão. Este valor está no formato de tempo GMT. Se o tempo do cliente e do servidor forem inconsistentes, haverá desvios ao usar expira.
MAX-AGE: A mesma função que expira é usada para dizer ao navegador quanto tempo esse cookie expira (em segundos), em vez de um ponto de tempo fixo. Em circunstâncias normais, o máximo tem maior prioridade do que expira.
Httponly: informa o navegador a não permitir que o documento de script.cookie altere esse valor, e esse valor também não é visível no document.cookie. Mas este cookie ainda será transportado com solicitação HTTP. Observe que, embora esse valor não esteja disponível no script, ele ainda existe no diretório de instalação do navegador como um arquivo. Essa configuração geralmente é definida no lado do servidor.
Seguro: sinalizador de segurança, depois de especificar, ele só pode ser enviado ao servidor ao usar o link SSL. Se for um link HTTP, essas informações não serão aprovadas. Mesmo que o atributo seguro esteja definido, isso não significa que outros não possam ver as informações de cookies salvas localmente em sua máquina; portanto, não coloque informações importantes em cookies e defina -as diretamente no lado do servidor.
Exemplos de cookies são os seguintes:
var http = requer ('http'); var fs = requer ('fs'); http.createServer (function (req, res) {res.SetHeader ('status', '200 ok'); res.Setheader ('set-cookie', 'isvisit = true; Mundo ');Definir o conjunto de conjuntos diretamente é muito original. Podemos encapsular o processo de configuração de cookies da seguinte forma:
var serille = function (nome, val, opções) {if (! name) {lança novo erro ("Cooleie deve ter nome"); } var enc = codeuricomponent; var peças = []; val = (val! == null && val! == indefinido)? val.toString (): ""; Opções = Opções || {}; parts.push (ENC (nome) + "=" + ENC (val)); // Deve haver dois pontos no domínio se (options.Domain) {parts.push ("domain =" + options.Domain); } if (options.path) {Parts.push ("path =" + options.path); } // Se você não definir expira e os navegadores da idade máxima limparão os cookies quando a página for fechada se (options.expires) {parts.push ("expires =" + options.expires.togmtString ()); } if (options.maxage && typeof options.maxage === "número") {parts.push ("max-age =" + options.maxage); } if (options.httponly) {parts.push ("httponly"); } if (options.secure) {Parts.push ("seguro"); } retornar partes.join (";");}Deve -se notar que, se um cookie estiver definido para um horário passado, o navegador excluirá o cookie imediatamente; Além disso, o item de domínio deve ter dois pontos, por isso não pode ser definido como localhost:
Algo que não ficou claro para mim aqui e me confundiu totalmente por um tempo que os nomes de domínio deveriam conter pelo menos dois pontos (.), Portanto, 'localhost' é inválido e o navegador se recusará a definir o cookie!
Cookies de análise do lado do servidor
Os cookies podem definir diferentes domínios e caminhos; portanto, para o mesmo valor, ele pode ser repetido sob diferentes caminhos em diferentes domínios e caminhos diferentes. O navegador classificará a ordem na ordem em que melhor corresponde ao endereço de URL ou página solicitado atual.
Portanto, quando o cookie passou para o lado do servidor, no lado atual, possui vários valores de nomes duplicados, precisamos apenas daquele que mais corresponde, ou seja, o primeiro. O código de análise do lado do servidor é o seguinte:
var parse = function (cstr) {if (! cstr) {return null; } var deC = decodeuricomponent; var cookies = {}; var peças = cstr.split (// s*;/s*/g); partes. Cookies [Nome] = Val; devolver cookies;}Acesso ao cliente
O navegador gerencia os cookies passados em segundo plano e permite que os desenvolvedores usem document.cookies em javascript para acessar cookies. Mas essa interface é muito coxa para usar. Ele mostrará comportamentos diferentes por causa das diferentes maneiras pelas quais é usado.
Quando usado para obter valores de atributo, Document.Cookie retorna todas as seqüências disponíveis na página atual (com base no domínio, caminho, caminho de validade e configurações de segurança do cookie). O formato da string é o seguinte:
"name1 = value1; nome2 = value2; nome3 = value3";
Quando usado para definir valores, a propriedade Document.Cookie pode ser definida como uma nova corda de cookie. Esta string é interpretada e adicionada à coleção de cookies existente. como:
document.cookie = "_fa = aaaffffasdsf; domain = .dojotoolkit.org; path =/"
Configurar document.cookie não substitui os cookies, a menos que o caminho do domínio do nome do nome definido seja repetido com um cookie existente.
Como é muito inconveniente ler e escrever cookies, podemos encapsular algumas funções para lidar com cookies, principalmente para a adição, modificação e exclusão de cookies.
var cookieutils = {get: function (nome) {var cookiename = codeuricomponent (name) + "="; // Obtenha o nome mais correspondente, valor var cookiestart = document.cookie.indexof (cookiename); var cookievalue = nulo; if (cookiestart> -1) {// de cookiestart var cookieend = document.cookie.indexof (';', cookiestatart); // de = depois = (cookieend> -1) {CookieValue = decodeuricomponent (document.cookie.substring (cookiestart + cookiename.length, cookieend)); } else {CookieValue = decodeuricomponent (document.cookie.substring (cookiestart + cookiename.length, document.cookie.length)); }} Retorne CookieValue; }, set: function (nome, val, opções) {if (! name) {lança um novo erro ("cooliie deve ter nome"); } var enc = codeuricomponent; var peças = []; val = (val! == null && val! == indefinido)? val.toString (): ""; Opções = Opções || {}; parts.push (ENC (nome) + "=" + ENC (val)); // O domínio deve conter dois pontos se (options.Domain) {parts.push ("domain =" + options.Domain); } if (options.path) {Parts.push ("path =" + options.path); } // Se você não definir expira e o navegador da idade máxima limpará os cookies quando a página for fechada se (options.expires) {Parts.push ("expires =" + options.path); } // Se você não definir expira e o navegador da idade máxima limpará os cookies quando a página for fechada se (options.expires) {parts.push ("expires =" + options.expires.togmtString ()); } if (options.maxage && typeof options.maxage === "número") {parts.push ("max-age =" + options.maxage); } if (options.httponly) {parts.push ("httponly"); } if (options.secure) {Parts.push ("seguro"); } document.cookie = partes.join (";"); }, excluir: function (nome, opções) {options.expires = new Date (0); // definido como a data passada. }}Vantagens do cache
O cache comumente chamado de Web refere -se a um dispositivo HTTP que pode salvar automaticamente cópias de solicitações HTTP comuns. Para desenvolvedores de front-end, os navegadores desempenham um papel importante. Além disso, existem vários servidores de proxy comuns que também podem ser usados para armazenamento em cache. Quando uma solicitação da Web atinge o cache, o cache extrai o conteúdo da réplica da réplica local sem passar pelo servidor. Isso traz as seguintes vantagens:
O cache reduz a transmissão de dados redundantes e economiza tráfego
O cache alivia problemas de gargalo de largura de banda. As páginas podem ser carregadas mais rapidamente sem mais largura de banda
O cache alivia o congestionamento instantâneo e reduz os requisitos para o servidor original.
O cache reduz o atraso da distância porque o carregamento de páginas de lugares mais distantes será mais lento.
Tipo de cache
O cache pode ser dedicado a um único usuário ou compartilhado por vários usuários. Um cache dedicado é chamado de cache privado, e um cache compartilhado é chamado de cache público.
Cache privado
O cache privado é apenas para usuários proprietários, por isso não requer muito espaço e é barato. Os navegadores da Web têm caches privados embutidos - a maioria dos navegadores abriga recursos comuns no disco e na memória do seu PC. Por exemplo, o local de armazenamento de cache do navegador Chrome é: c:/users/your_account/AppData/local/google/chrome/dados do usuário/inadimplência.
Cache público
Os caches públicos são servidores de proxy compartilhados especiais, chamados servidores de proxy de cache ou caches proxy (um objetivo de proxy reverso). O cache público aceitará o acesso de vários usuários, para que possa reduzir melhor o tráfego redundante.
Na figura abaixo, cada cliente acessará repetidamente um recurso ao servidor (ele não está no cache privado no momento), para acessar o servidor várias vezes, aumentando a pressão no servidor. Ao usar um cache público compartilhado, o cache só precisa ser recuperado do servidor uma vez e não precisa passar pelo servidor no futuro, o que pode reduzir significativamente a pressão no servidor.
De fato, o cache público hierárquico geralmente é usado em aplicações reais. A idéia básica é usar caches pequenos e baratos perto do cliente, enquanto em um nível mais alto, caches maiores e mais poderosos são gradualmente adotados para carregar recursos compartilhados por vários usuários.
Fluxo de processamento de cache
Para desenvolvedores de front-end, lidamos principalmente com caches no navegador, para que o processo acima seja simplificado para:
A figura a seguir mostra os resultados da solicitação de um site para diferentes recursos. Pode-se observar que alguns recursos são lidos diretamente do cache, alguns recursos são reverificados com o servidor e alguns recursos são requisitados no servidor.
Observe que todas as perguntas que discutimos sobre os recursos de cache são apenas para solicitações de GE Get. Para operações comportamentais, como Post, Excluir e colocar, geralmente não há cache.
Limite de frescura
O HTTP mantém uma cópia do recurso do servidor por um período de tempo através do cache, que é chamado de limite de frescura. Isso solicita o mesmo recurso por um período de tempo e não passará pelo servidor novamente. Controle de cache e expira no protocolo HTTP pode ser usado para definir o limite de frescura. O primeiro é o novo cabeçalho de resposta adicionado em HTTP1.1, e o último é o cabeçalho da resposta em HTTP1.0. Ambos fazem a mesma coisa, mas como o controle do cache usa tempo relativo e os expiros podem ter um problema de que o tempo do cliente e do servidor seja diferente, preferimos o controle de cache.
Controle de cache
Vamos dar uma olhada em quais valores de atributo podem ser definidos pelo Cache-Control:
O máximo de idade (unidade é s) especifica o tempo máximo válido para definir o cache, que define o tempo. Quando o navegador envia uma solicitação para o servidor, o navegador não enviará mais uma solicitação ao servidor durante o máximo.
<html> <head> <meta http-equiv = "content-type" content = "text /html; charset = utf-8"> <meta name = "viewport" content = "width = width, sem-lar, escala inicial = 1.0, máximo-escala = 1,0, user-scalable = não" /> /> <mta htta htt = 1.0, escala máxima = 1,0, user-scalable = não " />> Content = "ie = Edge"/> <title> cache da web </ititle> <link rel = "Ícone de atalho" href = "./ shortcut.png"> <cript> </sCript> </cheft> <l) <img src = "./ cache.png"> </body> </html> htt htt htt httrc = "./ cache.png"> </corpora requim ('fs'); http.createServer (function (req, res) {if (req.url === '/' || req.url === '' || req.url === '/index.html') {fs.readfile ('./ index.html', functml ') {) Para o documento principal, Res.SethEader ('Cache-Control', "No-Cache, Max-Arane" + 5); fs.readfile ('./ cache.png', function (err, file) {res.setheader ('cache-control', "max-age =" + 5); // cache cinco segundos res.setheader ('content-type', 'imagens/png'); }). Ouça (8888)Quando a página for acessada pela segunda vez em 5 segundos, o navegador obterá diretamente os recursos do cache
O público especifica que a resposta pode ser armazenada em cache no cache proxy e, portanto, pode ser compartilhada por vários usuários. Se privado não for especificado explicitamente, ele padrão é público.
A resposta privada só pode ser armazenada em cache no cache privada e não pode ser colocada no cache proxy. Recursos sensíveis a algumas informações do usuário geralmente precisam ser definidos como privados.
O NO-CACHE significa que você deve primeiro confirmar com o servidor se o recurso foi alterado (confiando no IF-None e ETAG) antes de decidir se o uso do cache local.
Se o processamento acima do cache.png for alterado para o seguinte, toda vez que você visitar a página, o navegador precisará ir ao servidor para verificar se o recurso foi alterado.
fs.readfile ('./ cache.png', function (err, file) {console.log (req.headers); console.log (req.url) if (! req.headers ['if-none-match']) {res.SetHeader ('cache-control', "não-cache, max-sna-sna-max) {res. (cache-cacheRol; 'imagens/png'); Res.Setheader ("Cache-Control", "Max-Arane" + 5);A não-loja proíbe Geralmente usado para recursos confidenciais.
Em relação ao uso de controle de cache, veja a figura abaixo (de grandes quantidades)
Limite de frescura do cliente
O controle de cache pode não apenas ser definido no cabeçalho da resposta, mas também no cabeçalho da solicitação. O navegador pode decidir se deve ler os recursos do cache definindo o controle de cache no cabeçalho da solicitação. É também por isso que às vezes clicando no botão de atualização do navegador e entrando na barra de endereços para ver resultados completamente diferentes no módulo de rede
Expira
Expira não é recomendado, ele especifica uma data de validade específica em vez de um número de segundos. Como muitos servidores e clientes têm relógio inconsistente, é melhor usar o controle de cache.
Verificação do servidor
O recurso em cache no navegador ou no cache proxy expira não significa que ele é realmente diferente dos recursos do servidor original, mas significa apenas que é hora de verificar. Esta situação é chamada de re-verificação do servidor.
Se o recurso mudar, você precisará obter novos recursos e substituir os recursos antigos no cache.
Se o recurso não foi alterado, o cache precisará obter apenas um novo cabeçalho de resposta e um novo tempo de validade para atualizar o tempo de validade do recurso no cache.
O método de verificação recomendado para http1.1 é se não-não-correspondência/etaG, e se modificado-uma vez/Última modificação é usada em http1.0.
ETAG e IF-NONE-MATCH
Gere uma string de hash com base no conteúdo da entidade, identificando o status do recurso e é gerado pelo servidor. O navegador passará essa sequência de volta ao servidor para verificar se o recurso foi modificado. Se não foi modificado, o processo é o seguinte (a imagem vem de uma breve discussão sobre cache da web):
Na demonstração acima, vimos como verificar o ETAG no servidor:
Como o ETAG tem uma estrutura de servidor, a singularidade de ETAG deve ser garantida no ambiente de cluster
Se modificado-uma vez vs. Última modificação
Esses dois são cabeçalhos de solicitação/resposta usados no HTTP 1.0 para verificar se o recurso expirou. Esses dois cabeçalhos são datas. O processo de verificação é semelhante ao ETAG, por isso não o apresentaremos em detalhes aqui. Ao usar esses dois cabeçalhos para verificar se o recurso é atualizado, existem seguintes problemas:
Alguns recursos do documento são reescritos periodicamente, mas o conteúdo real não mudou. No momento, os metadados do arquivo mostrarão que a data de modificação mais recente do arquivo é diferente de IF-modificada-uma vez, resultando em respostas desnecessárias.
Alguns recursos do documento foram modificados, mas o conteúdo da modificação não é importante e todos os caches não precisam ser atualizados (como comentários de código)
Em relação à atualização do cache, confira a resposta de Zhang Yunlong aqui. Este artigo não será expandido em detalhes.
O código de demonstração neste artigo é o seguinte:
<! Doctype html> <html> <head> <meta http-equiv = "content-type" content = "text /html; charset = utf-8"> <meta name = "viewport" content = "width = dispositivo-width, inicial = 1,0, maximum-escala = 1.0,, Usserve-scale, não-scale = 1 / / / / / /META (MENTAGEM". http-equiv = "x-ua compatível com" content = "ie = edge"/> <title> web cache </ititle> <link rel = "shortcut icon" href = ". requim ('http'); var fs = requim ('fs'); http.createServer (function (req, res) {if (req.url === '/' || req.url === '' || req.url ===/'/ndex.html') {fs.file (fs.file (fs. '| Console.Log (Req.url) // Defina o documento principal, sem efeito res.SETHEADER ('Cache-Control', "No-cache, Max-Arane" + 5); === '/shortcut.png') {fs.readfile ('./ shortcut.png', function (err, file) {console.log (req.url) res.setheader ('content-type', 'imagens/png'); res.writehead ('200', "Ok); '/cache.png') {fs.readfile ('./ cache.png', function (err, file) {console.log (req.headers); console.log (req.url) if (! req.headers ['if-not-match']) {res.SeTheader ('cache-cache'; Res.setheader ('Type', 'imagens/png'); Res. end (); }}). Ouça (8888)OK, a introdução deste artigo aos cookies termina aqui, espero que todos gostem.