> For the complete documentation index, see [llms.txt](https://yatax.leandronsp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yatax.leandronsp.com/protocolo-http.md).

# Protocolo HTTP

Vimos anteriormente como funciona a [comunicação TCP/IP](/comunicacao-tcp-ip.md) e como ela pode ser utilizada em uma arquitetura de rede cliente-servidor.&#x20;

![](/files/RPOOuLUfov6g7CnePxZJ)

O quê poderia acontecer caso a mensagem do cliente estivesse colocada de outra forma?

```
Client
-> QUERO fotos_da_festa.jpg
-> IWANT videos_de_domingo.mp4
-> PORFAVOR /hello

Server
-> if QUERO fotos_da_festa.jpg, then "Desculpa mas não tenho"
-> if IWANT videos_de_domingo.mp4, then "Aqui está!"
-> if PORFAVOR /hello, then "Hello client!"
```

Neste caso, diferentes clients poderiam enviar mensagens de diferentes formatos, cada qual com seu *próprio formato*, obrigado servers a saberem **interpretar** todos os formatos adequadamente.&#x20;

Como podemos então criar uma forma **padronizada** de mensagens, onde *clients e servers* pudessem todos utilizar o mesmo padrão? Quando queremos padronizar algo, geralmente criamos um **protocolo**.

Um protocolo é uma especificação bem definida e *documentada* de diretrizes e regras que, se seguidas, garantem que todas as partes possam estar uniformes. \
\
Para resolver o problema de padronizar mensagens na internet através de TCP/IP, foi criado um conjunto de especificações para envio com conteúdo que suportasse diferentes formatos (text, PDF, video etc), que se tornou o protocolo HyperText Transfer Protocol, ou [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol).

### O formato HTTP

Não esquecendo que a comunicação TCP/IP é baseada em client enviando um *request* e server enviando um *response*, logo o protocolo HTTP também está sujeito a tal característica.

#### Request

Um simples request com formato HTTP pode ser definido da seguinte forma:

```
GET /hello HTTP/2
```

Onde

* `GET` é o *verbo* da mensagem, neste caso remete semanticamente a "buscar algum recurso"
* `/hello` é o predicado da mensagem, remete a "caminho do recurso"
* `HTTP/2` é a versão do protocolo

#### Response

Já o response com formato HTTP pode ser algo do tipo:

```
HTTP/2 200

Hello
```

Onde

* `HTTP/2` representa a versão do protocolo
* `200` é o *código* status da resposta, que indica que o request foi recebido e interpretado com sucesso, retornando o que foi pedido
* `Hello` é o corpo da mensagem

### Informações adicionais no HTTP

E se quisermos enviar mais informações na mensagem HTTP, como por exemplo:

* o *tipo* de conteúdo que queremos enviar/receber
* quanto tempo o recurso deve "durar"
* o tamanho máximo permitido

...pra não mencionar diversas outras informações relevantes e que não são possíveis de enviar no **corpo** da mensagem? Para isto existem os HTTP headers. \
\
Portanto, podemos definir o template de uma mensagem HTTP como sendo da seguinte forma:

```
<request ou response>\r\n
Header1: valor1\r\n
Header2: valor2\r\n
\r\n
<corpo da mensagem>
```

O que são esses `\r\n` na mensagem? Este caracter é muito importante no protocolo HTTP, e pode ser explicado da seguinte forma:

* `\r` significa *carriage return*, move o cursor para o início da linha sem avançar para a próxima linha
* `\n` significa *line feed*, move o cursos para a próxima linha sem recuar para o início da linha
* `\r\n` é a combinação dos dois primeiros, ou seja, move o cursor para o início da próxima linha. É uma forma da mensagem ser consumida \*continuamente\* no socket TCP/IP até **não ter mais conteúdo no socket**.

### Um simples HTTP server em Ruby

Vamos então implementar uma simples comunicação HTTP **sem headers** em Ruby.

`client.rb`

```ruby
require 'socket'

server = TCPSocket.new('0.0.0.0', 3000)

request = %{
GET /hello HTTP/2\r\n
\r\n
\r\n
}

server.puts(request)

server.close
```

E vamos ao server:

`server.rb`

```ruby
require 'socket'

socket = TCPServer.new(3000)
puts 'Listening to the port 3000...'

loop do
  client = socket.accept

  request = client.gets
  puts "Request: #{request}"
  
  response = %{
HTTP/2 200\r\n
\r\n
\r\n
Hello
}
  client.puts(response)

  client.close
end

socket.close
```

Ao rodarmos `ruby server.rb` e `ruby client.rb`, conseguimos ver a mensagem "Hello" aparecendo no screen do client.&#x20;

Yay, nossa primeira implementação de HTTP em Ruby!&#x20;

[Mais detalhes no pull request](https://github.com/leandronsp/yatax/pull/2)
