Tópicos
1. Tópicos
2. Protocolo HTTP
2.1. Stateless
2.2. Estrutura
2.3. Requisições HTTP
a. GET
b. POST
c. PUT
d. DELETE
2.4. Respostas HTTP
a. JSON
b. XML
c. HTML
2.5. Arquivos
3. MIME-Type em Responses
4. URI vs. URL
5. Bônus - o cliente Curl: Uma Ferramenta Versátil para Requisições HTTP
5.1. Exemplos de Uso do Curl:
6. Conclusão
Introdução
Partindo do princípio que o leitor tem noções gerais de rede de computadores e conhecimento sobre a comunicação entre dispositivos através das redes e sabe o que é um protocolo de comunicação, este artigo trata sobre a arquitetura cliente-servidor e o protocolo HTTP.
A arquitetura cliente-servidor é um modelo de comunicação muito utilizado em sistemas distribuídos e aplicações web. Nesse modelo, o sistema é dividido em duas partes principais: o cliente e o servidor. O cliente é responsável por fazer solicitações ao servidor e processar as respostas recebidas. Já o servidor é responsável por receber as solicitações do cliente, processá-las e enviar as respostas de volta ao cliente.
A comunicação entre o cliente e o servidor na Web é geralmente realizada através do protocolo HTTP (Hypertext Transfer Protocol), que é amplamente utilizado na internet para a transferência de dados entre clientes e servidores.
Protocolo HTTP
O protocolo HTTP é baseado no modelo requisição-resposta, onde o cliente envia uma requisição ao servidor e o servidor responde com os dados solicitados ou um código de status indicando o resultado da operação.
É um protocolo baseado em texto (apesar de poder transportar dados binários) e utiliza o TCP (Transmission Control Protocol) como protocolo de transporte. O TCP é um dos principais protocolos da camada de transporte do modelo TCP/IP e é responsável por garantir uma comunicação confiável entre os dispositivos.
Ao utilizar o TCP como protocolo de transporte, o HTTP pode contar com mecanismos como confirmações de recebimento (ACKs), retransmissão de pacotes perdidos e controle de fluxo para garantir que os dados sejam entregues de forma confiável e em ordem.
O uso do TCP torna o HTTP uma escolha robusta para a transferência de dados na internet, especialmente para aplicações que exigem alta confiabilidade e precisão na entrega de informações.
Stateless
O protocolo HTTP (Hypertext Transfer Protocol) é considerado stateless, o que significa que cada requisição enviada pelo cliente ao servidor é tratada de forma independente e não contém informações sobre ações anteriores. Em outras palavras, o servidor não mantém informações sobre o estado da sessão ou interação com o cliente entre as requisições.
Algumas informações importantes sobre protocolos stateless:
- Cada requisição é tratada de forma independente.
- Não há armazenamento de informações de estado entre requisições.
- O servidor não mantém informações sobre as ações anteriores do cliente.
- A comunicação é mais simples e leve, pois não há necessidade de manter uma conexão contínua entre o cliente e o servidor.
- É mais escalável, pois cada requisição pode ser processada de forma isolada e distribuída entre diferentes servidores.
Essa natureza stateless do HTTP tem implicações importantes para o desenvolvimento de aplicações web. Como o servidor não mantém informações sobre o estado da sessão, todas as informações relevantes devem ser incluídas na própria requisição, geralmente através de cabeçalhos ou parâmetros na URL. Isso permite que o servidor trate cada solicitação de forma independente, tornando a comunicação mais simples e previsível.
Por outro lado, aplicações que exigem uma comunicação mais complexa e interativa, como sistemas de autenticação ou carrinhos de compras em e-commerce, podem enfrentar desafios adicionais ao trabalhar com o HTTP stateless. Nesses casos, podem ser necessárias técnicas adicionais, como o uso de cookies ou tokens, para manter informações de estado entre as requisições. Falaremos sobre isso em outros artigos futuros.
Estrutura
Uma requisição HTTP consiste em uma série de linhas de texto, separadas por \n
, que delimita uma linha. A requisição tem uma linha inicial contendo o método da requisição, o caminho do recurso desejado e a versão do protocolo, seguida por cabeçalhos opcionais e o corpo da requisição (opcional em algumas situações).
Exemplo de uma requisição HTTP:
GET /pagina.html HTTP/1.1
Host: www.exemplo.com
User-Agent: Mozilla/5.0
Uma resposta HTTP também consiste em uma linha inicial contendo a versão do protocolo, o código de status e uma frase descritiva, seguida por cabeçalhos opcionais e o corpo da resposta (opcional em algumas situações).
Exemplo de uma resposta HTTP:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
<html>
<head>
<title>Página de Exemplo</title>
</head>
<body>
...
</body>
</html>
Os cabeçalhos do protocolo HTTP são bastante numerosos, além de poderem ser definidos pela aplicação (ou seja, uma aplicação pode adicionar cabeçalhos não-padrões), tanto na requisição quanto na resposta. Para mais informações sobre os cabeçalhos http, vale dar uma olhada na página de cabeçalhos do HTTP do MDN Web Docs
A seguir, vamos detalhar um pouco mais a requisição (request) e a resposta (response) de mensagens deste protocolo.
Requisições HTTP
As requisições HTTP são a base da interação entre cliente e servidor na arquitetura cliente-servidor. Cada requisição é composta por um método, um caminho (URI – falaremos mais adiante sobre URI e URL) e uma versão do protocolo – esta é a primeira linha da requisição. Além disso, as requisições podem incluir cabeçalhos e um corpo com dados adicionais.
A definição do protocolo HTTP em sua versão mais usada atualmente (1.1) é feita na RFC 2616 (um documento que vale muito a leitura) e define os seguintes métodos para o HTTP:
- OPTIONS
- GET
- HEAD
- POST
- PUT
- DELETE
- TRACE
- CONNECT
Apesar disso, alguns métodos são mais utilizados e serão explicados melhor a seguir.
GET
O método GET é usado para solicitar a recuperação de um recurso específico no servidor. Ele envia os parâmetros na URL, geralmente na forma de cadeias de consulta (query strings). Este é o método mais utilizado na Web, pois é com ele que os browsers fazem a requisição para os servidores.
Exemplo de requisição GET:
GET /pagina.html?parametro1=valor1¶metro2=valor2 HTTP/1.1
Host: www.exemplo.com
Neste exemplo, apenas um cabeçalho extra está sendo enviado (Host: www.exemplo.com
), a URI é /pagina.html
e os parâmetros, enviados após o sinal de interrogação (?
) são parametro1=valor1
e parametro2=valor2
. Note também que, por ser uma requisição que utiliza o método GET
, não há uma linha em branco após os cabeçalhos, já que este método não suporta um corpo adicional.
POST
O método POST é usado para enviar dados ao servidor, geralmente para criar um novo recurso ou enviar informações sensíveis, como senhas ou dados de formulários.
Exemplo de requisição POST:
POST /criar_usuario HTTP/1.1
Host: www.exemplo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 27
nome=João&email=joao@example.com
Neste exemplo, alguns cabeçalhos extras estão sendo incluídos (Host: www.exemplo.com
, Content-Type: application/x-www-form-urlencoded
e Content-Length: 27
). Note que após os cabeçalhos há uma linha em branco (ou seja, duas quebras de linha seguidas – \n\n
). Esta linha indica ao servidor que receberá esta requisição que o cabeçalho do protocolo está terminado, e que todo dado que ainda for enviado fará parte do corpo. O cabeçalho Content-Length
indica quantos bytes o servidor deve esperar no corpo.
PUT
O método PUT é usado para enviar dados ao servidor para criar ou atualizar um recurso específico.
Exemplo de requisição PUT:
PUT /atualizar_usuario/123 HTTP/1.1
Host: www.exemplo.com
Content-Type: application/json
Content-Length: 47
{"nome": "Maria", "email": "maria@example.com"}
Neste exemplo, o tipo cabeçalho Content-Type
avisa ao servidor que os dados enviados estão no formato application/json
, e por conta disso é possível notar que o corpo da requisição contém dados em JSON (formato que será mais explorado adiante).
DELETE
O método DELETE é usado para solicitar a exclusão de um recurso específico no servidor.
Exemplo de requisição DELETE:
DELETE /excluir_usuario/456 HTTP/1.1
Host: www.exemplo.com
Respostas HTTP
As respostas HTTP são enviadas pelo servidor como resposta às requisições feitas pelo cliente. Cada resposta é composta por uma linha inicial contendo o código de status e a versão do protocolo, seguida pelos cabeçalhos e o corpo com os dados solicitados (se aplicável).
Os códigos de status são usados para indicar o resultado da requisição. Eles são divididos em classes numéricas que indicam o tipo de resposta. Alguns dos códigos de status mais comuns são:
2xx: Indica que a requisição foi bem sucedida, como por exemplo "OK" (200) ou "Created" (201).
3xx: Indica redirecionamento, como por exemplo "Found" (302).
4xx: Indica erros do cliente, como por exemplo "Not Found" (404) ou "Unauthorized" (401).
5xx: Indica erros no servidor, como por exemplo "Internal Server Error" (500).
O conteúdo das respostas podem ser de diversos tipos. A seguir, vamos falar um pouco sobre os mais comuns em aplicações web mais simples.
JSON
O JSON (JavaScript Object Notation) é um formato leve e amplamente utilizado para troca de dados entre cliente e servidor. Ele é fácil de ler e escrever para humanos e fácil de analisar e gerar para máquinas. Sua especificação pode ser acessada no site oficial, json.org.
Exemplo de resposta com JSON:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 56
{"nome": "João", "idade": 30, "email": "joao@example.com"}
Note que na resposta, após a linha inicial da resposta, existem alguns cabeçalhos (Content-Type: application/json
e Content-Length: 56
), e logo após uma linha em branco. Assim como na requisição, esta linha em branco indica ao cliente que está recebendo a resposta que acabaram os cabeçalhos, e que o que vem a seguir é o conteúdo (corpo) da resposta.
XML
O XML (eXtensible Markup Language) é outra opção para troca de dados entre cliente e servidor. Ele é mais verboso que o JSON, mas também é amplamente suportado e estruturado.
Exemplo de resposta com XML:
HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 143
<usuario>
<nome>João</nome>
<idade>30</idade>
<email>joao@example.com</email>
</usuario>
HTML
O HTML é usado para definir a estrutura e o layout de páginas web. As respostas HTML são renderizadas pelos navegadores para exibir conteúdo aos usuários.
Exemplo de resposta com HTML:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
<!DOCTYPE html>
<html>
<head>
<title>Página de Exemplo</title>
</head>
<body>
<h1>Olá, mundo!</h1>
</body>
</html>
Arquivos
As respostas também podem conter arquivos binários, como imagens, vídeos, documentos, etc. Nesses casos, o servidor define o cabeçalho Content-Type
apropriado para indicar o tipo de arquivo.
Exemplo de resposta com arquivo:
HTTP/1.1 200 OK
Content-Type: image/jpeg
Content-Length: 45678
<dados binários do arquivo>
Neste exemplo, o Content-Type
do cabeçalho está informando ao cliente que o corpo da resposta tem os dados binários de uma imagem no formato JPG. Considerando a importância de conhecer este cabeçalho, vamos falar um pouco mais sobre ele.
MIME-Type em Responses
O MIME-Type (Multipurpose Internet Mail Extensions) é um tipo de dado que indica o formato e o tipo de conteúdo presente em uma resposta HTTP. Ele é especificado através do cabeçalho Content-Type
. O MIME-Type é essencial para que o cliente saiba como interpretar e processar o conteúdo da resposta corretamente.
Por exemplo, o Content-Type
pode ser definido como application/json
para indicar que a resposta contém dados no formato JSON, ou como text/html
para indicar que a resposta é uma página HTML, ou text/css
para indicar que a resposta trata-se de um arquivo de folha de estilos CSS.
Você pode encontrar mais informações sobre os diferentes tipos de MIME-Type no MDN Web Docs.
URI vs. URL
URI (Uniform Resource Identifier) e URL (Uniform Resource Locator) são conceitos relacionados, mas não idênticos.
Uma URI é uma sequência compacta de caracteres que identifica um recurso abstrato ou físico, que pode ser um documento, imagem, serviço, etc. A URI é uma terminologia genérica que inclui URLs e URNs (Uniform Resource Names).
Uma URL é um tipo específico de URI que fornece os meios para localizar um recurso através de sua representação como uma sequência de caracteres. A URL inclui o esquema (como HTTP ou FTP), o domínio ou endereço IP, a porta, o caminho e os parâmetros.
Em resumo, toda URL é uma URI, mas nem toda URI é uma URL. Por exemplo, a URI urn:isbn:0451450523 identifica unicamente um livro pelo seu número ISBN, mas não é uma URL, pois não indica como acessar o recurso.
Para mais informações sobre URI e URL, você pode consultar o artigo da Wikipedia.
Bônus - o cliente Curl: Uma Ferramenta Versátil para Requisições HTTP
O curl é uma ferramenta de linha de comando amplamente utilizada para fazer requisições HTTP e interagir com diversos tipos de serviços na web. Com ele, é possível realizar operações como enviar dados para APIs, realizar testes de conectividade e até mesmo baixar arquivos. A versatilidade e simplicidade do curl o tornam uma escolha popular entre desenvolvedores e administradores de sistemas.
Exemplos de Uso do Curl:
Requisição GET para uma API de Teste: JSONPlaceholder
A JSONPlaceholder é uma API de teste que fornece dados fictícios em formato JSON para fins de desenvolvimento e teste. Vamos usar o curl para fazer uma requisição GET para a rota "/users/1" e obter os dados do usuário com id 1
.
curl https://jsonplaceholder.typicode.com/users/1
Podemos também adicionar o argumento -v
para que o Curl exiba também os cabeçalhos, tanto do request quanto do response:
curl -v https://jsonplaceholder.typicode.com/users/1
Nesse caso, a resposta será algo como
> GET /users/1 HTTP/2
> Host: jsonplaceholder.typicode.com
> user-agent: curl/7.88.1
> accept: */*
>
< HTTP/2 200
< date: Tue, 25 Jul 2023 18:29:21 GMT
< content-type: application/json; charset=utf-8
< content-length: 509
< x-powered-by: Express
< x-ratelimit-limit: 1000
< x-ratelimit-remaining: 998
< x-ratelimit-reset: 1689692921
< vary: Origin, Accept-Encoding
< access-control-allow-credentials: true
< cache-control: max-age=43200
< pragma: no-cache
< expires: -1
< x-content-type-options: nosniff
< etag: W/"1fd-+fao8fhs8ofnuo93no"
< via: 1.1 vegur
< cf-cache-status: HIT
< age: 160
< accept-ranges: bytes
< nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
< server: cloudflare
< alt-svc: h3=":443"; ma=86400
<
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
* Connection #0 to host jsonplaceholder.typicode.com left intact
}
Note que as primeiras linhas começam com o caracter >
, indicando que esta é uma linha da requisição; após uma linha em branco (>
apenas), seguem uma sucessão de linhas começadas por <
, indicando os cabeçalhos da resposta. Após uma linha em branco da resposta, indicada por um <
vazio, começam os dados da resposta. Note a grande quantidade de cabeçalhos que é trocado em cada request/response ;)
Requisição POST para Enviar Dados para uma API: ReqRes.in
O ReqRes.in é outra API de teste que permite fazer requisições HTTP simuladas. Vamos usar o curl para fazer uma requisição POST e enviar dados JSON para a rota "/users" com o objetivo de criar um novo usuário.
curl -X POST -H "Content-Type: application/json" -d '{"name": "John Doe", "job": "Developer"}' https://reqres.in/api/users
Conclusão
Este artigo fornece uma introdução à arquitetura cliente-servidor e ao protocolo HTTP, que são conhecimentos importantes para aqueles que desejam trabalhar com o desenvolvimento de Aplicações para Web.
É importante ressaltar, entretanto, que não abordamos aqui algumas questões importantes relacionadas à segurança e métodos de autenticação, mas que serão abordados eventualmente em outros artigos.
Top comments (0)