Cabeçalhos HTTP essenciais: cache, CORS e cookies
A maior parte da 'política' de uma requisição não está no corpo — está em headers que você raramente lê.
Quando você chama fetch(), o navegador cuida de um monte de coisa por trás sem avisar — se pode reusar uma resposta em cache, se um site diferente tem permissão de ler essa resposta, se deve mandar o cookie de sessão junto. Tudo isso é decidido por headers, não pelo código que você escreveu.
Cache-Control e ETag — evitando repetir trabalho
Cache-Control: public, max-age=3600
// "pode guardar essa resposta em cache por 3600 segundos (1h);
// depois disso, precisa perguntar de novo ao servidor"
Cache-Control: no-store
// "nunca guarde isso em cache, nem localmente" — típico de dado sensívelQuando o max-age expira, o navegador não precisa necessariamente baixar o arquivo inteiro de novo. Ele pode mandar o ETag (um identificador — geralmente um hash — que o servidor gerou da última vez) de volta, perguntando se ainda é válido:
// primeira resposta do servidor
HTTP/1.1 200 OK
ETag: "a3f9e2"
// requisição seguinte, depois do cache expirar
GET /produtos HTTP/1.1
If-None-Match: "a3f9e2"
// se o conteúdo NÃO mudou:
HTTP/1.1 304 Not Modified
// (sem corpo — o navegador reusa a versão que já tinha)CORS — por que um site não lê a resposta de outro por padrão
Por segurança, o navegador aplica a same-origin policy: JavaScript rodando em app.exemplo.com não consegue ler a resposta de uma requisição pra api.outraempresa.com, a menos que essa API explicitamente autorize, via header Access-Control-Allow-Origin. Sem CORS, qualquer site malicioso poderia usar sua sessão logada pra ler dados de outro serviço em seu nome.
Access-Control-Allow-Origin: https://app.exemplo.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type, AuthorizationPra requisições que não são "simples" (métodos além de GET/POST básico, ou headers customizados como Authorization, ou Content-Type: application/json), o navegador manda um preflight request antes — um OPTIONS perguntando "essa requisição vai ser permitida?" — e só envia a requisição real se a resposta do preflight disser que sim.
Exercício
Uma chamada fetch para POST https://api.exemplo.com/pedidos, com Content-Type: application/json, feita a partir de https://app.exemplo.com, dispara uma requisição OPTIONS antes da de verdade. Por que ela é considerada "não simples", e o que a API precisa responder pro navegador deixar a requisição real acontecer?
Set-Cookie e sessão — como o servidor "lembra" de você
HTTP não guarda estado entre requisições por conta própria — cada requisição chega "sem memória" da anterior. Login funciona porque o servidor manda um Set-Cookie na resposta, e o navegador reenvia esse valor automaticamente em toda requisição seguinte pro mesmo domínio.
Set-Cookie: sessao=abc123; HttpOnly; Secure; SameSite=Lax; Max-Age=86400HttpOnly → JavaScript no navegador não consegue ler esse cookie (reduz o
impacto de um ataque XSS que tentasse roubar a sessão)
Secure → só é enviado em conexões HTTPS, nunca em HTTP puro
SameSite → controla se o cookie é enviado em requisições vindas de outro
site (proteção contra CSRF)