Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

O Protocolo HTTP

Vimos que aplicações são compostas de vários componentes que se comunicam entre si: frontend (web e/ou mobile), backend, banco de dados, etc. Apesar de não ser uma regra, hoje em dia praticamente toda aplicação realiza a comunicação entre frontend e backend utilizando um protocolo da camada de aplicação chamado HTTP (HyperText Transfer Protocol).

Modelo Cliente-Servidor

Sempre que temos uma conversa que segue o protocolo HTTP, são definidos dois papéis essenciais:

  • O servidor HTTP: É um host que fica sempre escutando por novas conexões. Ele recebe requisições dos clientes e responde elas. Por exemplo, imagine que você acessa o SIGAA em http://sigaa.ufs.br/. Nesse caso, o servidor HTTP é o próprio sigaa.ufs.br (este é o FQDN do host que executa, ou hospeda, o SIGAA).
  • O cliente HTTP: É o host que inicia novas conexões. É ele quem manda as requisições para o servidor e fica aguardando pela resposta dele. No exemplo anterior, quando você acessa o SIGAA em http://sigaa.ufs.br/, você é o cliente HTTP. Note que é possível que dois ou mais clientes HTTP diferentes conectem-se ao mesmo servidor HTTP.

Ou seja, o protocolo HTTP segue o chamado Modelo Cliente-Servidor. A imensa maioria dos protocolos da camada de aplicação seguem esse modelo1.

Figura 2-7: O cliente inicia a conexão e envia requisições; o servidor aguarda e responde.

Mensagens HTTP: Requisições e Respostas

Toda conversa entre o cliente e o servidor é uma sequência de mensagens HTTP. Uma mensagem HTTP pode ser de dois tipos: uma Requisição HTTP (enviada pelo cliente para o servidor) ou uma Resposta HTTP (enviada pelo servidor para o cliente).

Figura 2-8: Ciclo HTTP: o cliente envia uma requisição e o servidor retorna uma resposta.

Anatomia de uma Requisição HTTP

Toda comunicação HTTP começa por uma requisição, pois é o cliente quem inicia a comunicação. O servidor fica passivamente aguardando novas conexões iniciadas pelos clientes.

Vamos primeiro ver um exemplo de requisição HTTP2. A requisição abaixo é de um cliente que está acessando uma página web sobre um relatório do clima.

Figura 2-9: Partes de uma requisição HTTP: request line (método, path, query, versão), headers e payload.

GET /blog/2026/08/relatorio-clima.html?page=2&sort=date&highlight=temperatura HTTP/1.1
Host: www.guardian.co.uk
Accept: text/html
Accept-Language: pt-BR
User-Agent: Chrome/127.0.0.0
Cookie: session_id=a3f8b2c1e9d04716; _ga=GA1.2.1847263950.1723641200; consent=accepted
Connection: keep-alive

Vamos entender parte por parte:

  • A primeira linha é a linha de requisição (request line). Ela contém 4 partes:

    • Um método (GET, especificando que quer obter/ver algum conteúdo).
    • Um path (/blog/2026/08/relatorio-clima.html, especificando a localização do conteúdo que será visto).
    • Uma query string (?page=2&sort=date&highlight=temperatura, especificando parâmetros para mudar/personalizar o conteúdo retornado).
    • A versão do protocolo HTTP (HTTP/1.1, especificando quais funcionalidades HTTP estão disponíveis).
  • As próximas 6 linhas são cabeçalhos (headers) HTTP. Cada cabeçalho tem um nome (ex: Host) e um valor (ex: www.guardian.co.uk) separados por :.

    Os cabeçalhos HTTP permitem configurar a conexão e manter valores (estado) ao longo dela.

    • O header Host: www.guardian.co.uk especifica o host sendo acessado3.
    • Accept: text/html especifica qual o tipo esperado do conteúdo. Nesse caso, é esperado um conteúdo de texto que forma um documento HTML. Veremos mais a frente o que é um documento HTML.
    • Accept-Language: pt-BR especifica que o conteúdo deve ser retornado preferencialmente em Português do Brasil.
    • User-Agent: Chrome/127.0.0.0 indica que o cliente acessou o servidor por meio do navegador Google Chrome na versão 127.0.0.0. O valor desse header muda a depender do programa usado para acessar o site, podendo ser desde navegadores até ferramentas CLI como curl.
    • Cookie: session_id=a3f8...; _ga=GA1.2...; consent=accepted é o header que armazena os famosos cookies do site. Esse header guarda 3 cookies:
      • session_id é o ID de uma sessão específica do usuário naquele site. É por meio desse cookie que é possível fechar um site e, ao reabrí-lo, ainda estarmos conectados na nossa conta.
      • _ga é um cookie usado pelo Google Analytics, um serviço da Google que os sites contratam para poder rastrear e analisar o tráfego dos usuários, coletando dados como páginas visualizadas, duração da sessão, localização geográfica, tipo de dispositivo, etc.
      • consent é um cookie usado para identificar se um usuário consentiu com os termos de uso do site, como os cookies que são utilizados para rastrear o comportamento do usuário. É relevante principalmente em países que possuem legislação sobre uso de dados, como a LGPD.
    • Connection: keep-alive especifica que o clienter quer re-utilizar a mesma conexão TCP, re-aproveitando as configurações já feitas.
  • Após os headers pode vir uma ou mais linhas que formam o payload (ou corpo) da requisição. Como trata-se de uma requisição GET, não há necessidade de payload.

Método

Cada requisição HTTP possui um método (também chamado de verbo). O método HTTP representa que tipo de ação aquela requisição pretende realizar. Os 5 principais métodos HTTP são:

  • GET: Representa a ação de exibir um conteúdo ou listar os conteúdos existentes.
  • POST: Representa a ação de criar um conteúdo.
  • PUT: Representa a ação de substituir/modificar um conteúdo por completo.
  • PATCH: Representa a ação de substituir/modificar partes de um conteúdo.
  • DELETE: Representa a ação de remover um conteúdo.

As requisições que usam os métodos POST, PUT e PATCH costumam possuir uma payload (corpo da requisição), contendo os dados sobre o que será criado/modificado.

Veremos mais a frente como o padrão REST utiliza esses métodos para representar o gerenciamento de recursos.

Path

Uma requisição HTTP sempre diz respeito a algum conteúdo ou recurso. O path (caminho) da requisição indica o caminho daquele conteúdo/recurso em específico.

Por exemplo:

  • O path / é geralmente usado para representar a raiz daquele site, e geralmente retorna a página inicial do site.
  • O path /blog pode ser usado para representar todas as postagens do blog de um determinado site.
  • O path /blog/2026 pode ser usado para representar todas as postagens do blog do ano de 2026.
  • O path /blog/2026/08/relatorio-clima.html pode ser usado para representar uma postagem em específico do blog. Note que o path termina em .html, indicando que esse recurso trata-se de um arquivo/documento HTML.
  • O path /blog/imagens/banner.png representa uma imagem em específico do blog. Note que o path termina em .png, indicado que esse recurso trata-se de uma imagem PNG.
  • O path /api/usuarios/42 representa o recurso do tipo usuário cujo ID é igual a 42.

Query String

Dado um path, é possível que queiramos customizar o conteúdo retornado. Essas customizações normalmente são especificadas na parte da requisição chamada query string (também chamada de query parameters).

Geralmente, essas customizações costumam ser:

  • Qual filtro de busca utilizar
  • Qual página dos resultados deve ser retornada
  • Se os resultados devem ser ordenados, crescentemente ou decrescentemente.

A query string é uma lista de pares parâmetro=valor, separador por &. A lista de query parameters sempre começa com ?. Por exemplo, veja a query string do exemplo, ?page=2&sort=date&highlight=temperatura. Temos 3 parâmetros:

  • page=2 especifica que deve ser retornada a segunda página de resultados.
  • sort=date especifica que os resultados devem vir ordenados pela data.
  • highlight=temperatura especifica que o campo temperatura deve ter destaque.

Nem toda requisição tem uma query string. Ela é opcional.

A junção do path + query params formam o alvo da requisição.

Um dos benefícios dos query params é que como eles fazem parte do alvo da requisição, eles podem ser salvos e uma dada consulta (com seus filtros e opções) pode ser salvo e reutilizado. Por exemplo, o seguinte pode ser colado na barra de navegação para levar a uma consulta do Google pelo termo ufs: https://www.google.com/search?q=ufs. Veja que é utilizado o path /search e a query string ?q=ufs.

Versão HTTP

Toda requisição HTTP inclui a versão do protocolo que será utilizada. Atualmente, existem 4 versões em uso:

  • HTTP/1.0: Versão definida na RFC 1945. Estabeleceu os fundamentos do protocolo. Alguns servidores antigos ainda utilizam essa versão.
  • HTTP/1.1: Definida na RFC 2616. Estabeleceu otimizações importantes, como conexões persistentes (Connection: keep-alive). É a versão mais comum de ser vista na Internet.
  • HTTP/2: Protocolo deixou de ser baseado em texto e se transformou num protocolo binário. Funcionalidades: Multiplexação de várias mensagens sobre um mesmo canal de comunicação, compressão de cabeçalhos, priorização de arquivos, server push, etc.
  • HTTP/3: Versão mais recente, ainda pouco utilizada. Funcionalidades: troca do protocolo TCP pelo protocolo QUIC, criptografia obrigatória, mais rápido, etc.

Apesar disso, você só lerá requisições mencionando as duas primeiras versões, pois elas são baseadas em texto, já o HTTP/2 e o HTTP/3 são protocolos binários (não são legíveis por humanos).

Headers

Os campos anteriores juntos formam a linha de requisição (request line) de uma requisição HTTP. A request line é a primeira linha da requisição. Alguns exemplos de request lines:

  • GET /index.html HTTP/1.1
  • GET /search?q=openai&lang=en HTTP/1.1
  • POST /api/usuarios HTTP/1.1

Além da request line, uma requisição HTTP também possui os cabeçalhos (headers). Os headers são pares Nome: Valor e servem para adicionar metadados e configurações para a comunicação em si.

Alguns exemplos de headers relevantes:

  • Host. Especifica qual o FQDN do host que atua como servidor HTTP3. Esse é o único header de requisição que é obrigatório.

    Exemplo: Host: www.exemplo.com.

  • Cookie. É o header cujo valor são os famosos cookies do site. Esses cookies são utilizados para guardar informações que persistem ao longo de várias requisições HTTP (estado). Cada cookie é um par nome=valor, separados por ;.

    Exemplo: Cookie: session_id=abc123def456; theme=dark; lang=pt-BR, com 3 cookies.

  • Referer. É o header utilizado quando um site te redireciona para outro, e o seu valor é a URL do site que solicitou o redirecionamento.

    Exemplo: Referer: https://www.example.com/products?category=shoes.

Os headers vêm após a request line. Cada header é escrito em uma linha.

Payload

Quando a requisição HTTP usa métodos como POST, PUT e PATCH, ela inclui um payload (também chamado de corpo da requisição).

Por exemplo, considere a seguinte requisição, que cria uma nova usuária em um sistema:

POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 68

{"name":"Alice Morrow","email":"alice@example.com","age":29,"active":true}

Vamos entender por partes:

  • A request line é POST /api/users HTTP/1.1. Portanto, ela irá incluir um payload. Após a request line, seguem 3 headers.

    1. Host: example.com é o host que atua como servidor HTTP.
    2. Content-Type: application/json é um header que especifica qual o tipo do conteúdo que está no payload. Nesse caso, application/json indica que o payload segue o formato JSON, que veremos mais a frente.
    3. Content-Length: 68 é um header que especifica o tamanho do payload em bytes.
  • Após os 3 headers, temos uma linha em branco, que serve para indicar que a lista de headers acabou e o payload virá em seguida.

  • O conteúdo do payload é:

    {"name":"Alice Morrow","email":"alice@example.com","age":29,"active":true}
    

    Os dados desse payload contêm o nome, email, idade e o status de ativação da nova usuária.

Anatomia de uma Resposta HTTP

Toda requisição HTTP precisa ser respondida pelo servidor. Uma resposta HTTP tem uma estrutura mais simples que as requisições.

Suponha que fizemos uma requisição da forma GET /index.html HTTP/1.1. É uma requisição para a página inicial de algum site. A resposta que o servidor HTTP entregou foi:

HTTP/1.1 200 OK
Date: Sun, 16 Aug 2026 18:37:12 GMT
Server: Nginx/1.25.2
Content-Type: text/html; charset=utf-8
Content-Length: 171
Connection: keep-alive

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Página Inicial</title>
</head>
<body>
    <h1>Seja bem-vindo!</h1>
    <p>A página carregou com sucesso.</p>
</body>
</html>

Vamos analisar por partes:

  • A primeira linha é a linha de resposta (response line), contendo:
    • A versão do protocolo (HTTP/1.1)
    • O status code (200)
    • A reason phrase (OK), uma texto legível explicando o status code. Um status code sempre terá a mesma reason phrase. 200 OK = sucesso.
  • Segue-se uma linha para cada cabeçalho de resposta (response header). Perceba que alguns headers também podem aparecer em requisições:
    • Date: Sun, 16 Aug 2026 18:37:12 GMT indica o horário que o servidor mandou a resposta.
    • Server: Nginx/1.25.2 indica qual o programa ou biblioteca utilizado pelo servidor para enviar respostas HTTP.
    • Content-Type: text/html; charset=utf-8 indica que o corpo da resposta vem no formato HTML e foi codificado utilizando o padrão UTF-8.
    • Content-Lenght: 171 indica que o corpo da resposta tem 171 bytes.
    • Connection: keep-alive indica que deve ser re-utilizada a mesma conexão TCP.
  • Uma linha em branco indica o fim da lista de headers e o início do corpo da resposta.
  • Seguem 171 bytes que formam o corpo da resposta. A resposta é um document no formato HTML que será exibido para o usuário, montando a estrutura e o conteúdo da página inicial.

Status Code e Reason Phrase

O servidor irá indicar o tipo de resultado usando o status code, que é um código de 3 dígitos. O status code pode indicar se foi falha, falha por erro do cliente, falha por erro do servidor, redirecionamento, timeout, etc).

Todo status code está associado a um texto legível chamado reason phrase, dando mais detalhes do que aconteceu para além do código numérico.

Os status codes podem ser classificados em categorias de acordo com o primeiro dígito:

CategoriaTipoExemplos
1xxInformação100 Continue
101 Switching Protocols
2xxSucesso200 OK
201 Created
3xxRedirecionamento301 Moved Permanently
302 Found
4xxErro do Cliente400 Bad Request
403 Forbidden
404 Not Found
5xxErro do Servidor500 Internal Error
502 Bad Gateway
503 Service Unavailable

Você pode consultar todos os status codes, seus significados e dicas de como usá-los na referência da MDN: Códigos de status de respostas HTTP.

Headers

Assim como as requisições, as respostas HTTP possuem headers para carregar metadados e configurar a conexão.

Alguns headers são exclusivos das respostas, como Server. Já outros podem ser usados tanto por requisições como por respostas, como Connection, Content-Type e Content-Length.

Body/Corpo

A parte mais importante de uma resposta HTTP é o corpo (body). É nele que está o conteúdo que o cliente está interessado. Esse conteúdo geralmente é:

  • Um documento HTML, que define a estrutura e o conteúdo de uma página web.
  • Uma arquivo de mídia (imagem, áudio, vídeo)
  • Dados no formato XML ou JSON

O corpo da resposta pode ser vazio somente em algumas ocasiões, como em resposta a uma requisição DELETE.


  1. Apesar da maioria dos protocolos da camada de aplicação seguirem o Modelo Cliente-Servidor, existem alguns protocolos que seguem outro modelo, chamado de Modelo Peer-to-Peer (P2P), onde cada host atua como um misto de cliente e servidor, falando em pé de igualdade com outros hosts. O exemplo clássico é o protocolo BitTorrent, mas também existem outros como o protocolo Bitcoin e XMPP/Jabber. ↩

  2. Para simplificar, o exemplo mostrado omite os caracteres que representam as quebras de linhas (\r\n) numa requisição. Esses caracteres são importantes para indicar quando uma seção da requisição termina e outra começa. ↩

  3. Os mais atentos podem estar se perguntando qual a necessidade do header Host se, para iniciar a comunicação HTTP, o cliente precisa saber antecipadamente qual o host que atuará como servidor. O motivo é que o header Host é utilizado para implementar uma técnica conhecida como virtual hosting, onde um único host físico, com um único IP, hospeda várias aplicações HTTP diferentes (chamados de hosts virtuais). O host físico que atua como servidor olha o valor desse header para saber qual aplicação/host virtual o cliente está interessado.

    Inclusive, é por esse motivo que o header Host é o único que é obrigatório. Uma requisição sem ele será rejeitada pelo servidor. ↩ ↩2