Você pode ler sobre isso com detalhes exorbitantes na especificação HTTP , mas aqui está a essência: quando o navegador precisa solicitar um arquivo, ele primeiro verifica seu cache local. Existem três possibilidades principais:
- O navegador tem uma versão local (em cache) do arquivo que está marcado como expirando em um determinado horário, e esse horário está no futuro. Nesse caso, o navegador tem a opção de usar a versão em cache como está ou enviar uma solicitação ao servidor para ver se o arquivo foi alterado. Se o navegador enviar a solicitação, ela incluirá um cabeçalho
If-Modified-Since
contendo a hora em que o arquivo foi acessado pela última vez. - O navegador tem uma versão em cache do arquivo que já expirou. Nesse caso, o navegador definitivamente enviará uma solicitação ao servidor para ver se há uma nova versão, e essa solicitação incluirá (geralmente) um cabeçalho
If-Modified-Since
contendo a hora em que o arquivo foi acessado pela última vez. - O navegador não tem o arquivo armazenado em cache, e nesse caso ele envia uma solicitação sem cabeçalho
If-Modified-Since
.
Quando o pedido chega ao servidor, existem basicamente algumas coisas que podem acontecer. Se a solicitação não incluir um If-Modified-Since
header, o servidor irá adiante e enviará de volta o arquivo usando um código de resposta HTTP 200 (OK). (Ou ele enviará um 404 File Not Found, ou 403 Forbidden, ou o que for apropriado) Mas se o pedido fez incluir um If-Modified-Since
header, o servidor sabe que ele só precisa enviar de volta o arquivo se foi modificado desde o tempo contido no cabeçalho. Agora, se o arquivo foi modificado desde então, novamente, o servidor enviará de volta o arquivo com um código de 200, ou 403, 404, o que for. Mas se o arquivo não foi modificado desde o tempo especificado - o que, lembre-se, significa que a versão em cache do navegador ainda é atual - o servidor pode responder com um código 304 (não modificado) e deixar de fora o conteúdo do próprio arquivo. Isso economiza um pouco do tráfego de rede.
Agora, supondo que o servidor responda com todo o conteúdo do arquivo, existem algumas maneiras de fazer isso, dependendo de como o servidor está escrito e / ou configurado. Obviamente, ele poderia apenas ler o arquivo do disco (ou rodar o programa para gerá-lo, se é uma página dinâmica) toda vez que uma requisição entrar e apenas enviá-la de volta, mas como você sabe, isso é meio ineficiente. Uma coisa que o servidor pode fazer é enviar de volta uma versão gzipada do arquivo, se o navegador especificar Accept-Encoding: gzip
em sua solicitação. Na verdade, faz sentido para o servidor manter uma versão em cache do arquivo compactado, e o Apache (e provavelmente a maioria dos outros servidores) pode ser configurado para fazer isso. Quando o servidor está se preparando para enviar de volta uma resposta gzipada, ele verifica o tempo de modificação da versão em cache gzipada em relação à hora de modificação do arquivo original, e se o arquivo original tiver sido atualizado, executará o gzip novamente e substituirá o arquivo original. versão antiga no cache com a nova versão.
Às vezes, os servidores também podem armazenar arquivos em cache na RAM, se forem solicitados com frequência. Eu acho que o Apache pode ser configurado para fazer isso, mas não tenho certeza. (Como você provavelmente já pode adivinhar, com o Apache, é tudo sobre a configuração.)
Com relação à sua pergunta sobre como os arquivos são solicitados, o navegador realmente solicita os arquivos, um de cada vez. Cada página HTML, arquivo CSS, arquivo Javascript, arquivo de imagem, etc. corresponde a uma solicitação HTTP individual. Uma ferramenta como Wireshark pode realmente mostrar as solicitações e respostas HTTP individuais indo e voltando do seu computador, se você estiver interessado. Mas, para economizar recursos, a conexão TCP / IP normalmente permanece aberta por meio de um conjunto inteiro de solicitações. Por exemplo, se você tem uma página da Web com 3 imagens e uma folha de estilo CSS, provavelmente obteria uma sequência como esta:
- O navegador abre a conexão
- O servidor confirma a conexão
- O navegador solicita a página HTML
- O servidor envia a página HTML
- O navegador solicita a folha de estilo CSS
- O servidor envia uma folha de estilo CSS
- O navegador solicita a imagem 1
- O servidor envia a imagem 1
- O navegador solicita a imagem 2
- O servidor envia a imagem 2
- O navegador solicita a imagem 3 com
Connection: close
header - O servidor envia a imagem 3
- O servidor fecha a conexão
O cabeçalho Connection: close
pode ser enviado por qualquer um dos lados para especificar que a conexão TCP / IP deve ser encerrada após a conclusão da solicitação.
Espero que isso atinja principalmente o que você estava perguntando, mas a especificação HTTP é um documento ENORME e há muitas sutilezas que negligenciei. Eu realmente acho isso leitura moderadamente interessante, então eu sugiro que você dê uma olhada nisso (então, novamente, eu sou provavelmente meio estranho).