> For the complete documentation index, see [llms.txt](https://web101.leandronsp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://web101.leandronsp.com/construindo-um-simples-echo-web-server/adicionando-html.md).

# Adicionando HTML

Na última seção construímos a primeira versão do nosso simples HTTP server, que envia uma mensagem `PONG` em plain text.&#x20;

Mas como estamos falando de Web, seria mais adequado enviarmos HTML no body, não?&#x20;

Vamos modificar o server para responder um **content-type header** `text/html`, indicando que o client deve saber *renderizar HTML*, bem como fazendo com que o body seja um **parágrafo** HTML, no caso colocando a palavra **PONG** dentro da HTML tag `<p>`.

```bash
## Server
$ echo -e "HTTP/1.1 200\r\n\
Content-Type: text/html\r\n\
\r\n\
<p>PONG</p>" | nc -lvN 8080

Listening on 0.0.0.0 8080
```

Do lado do client, não precisamos mais de body. Podemos, por exemplo, indicar que queremos uma rota/caminho para o recurso `/ping`, deixando assim nossa comunicação HTTP mais semântica.&#x20;

```bash
## Client
$ echo -e "GET /ping HTTP/1.1\r\n\
Content-Type: text/html\r\n\
\r\n" | nc -v localhost 8080

HTTP/1.1 200
Content-Type: text/html

<p>Hello</p>
```

Podemos ver que, apesar do HTTP header indicar que o tipo do conteúdo é HTML, o comando `netcat` do lado do client não sabe renderizar.&#x20;

Isto porque, para renderizar HTML, é preciso ter um motor de renderização, coisa que os Web browsers implementam. Vamos experimentar outros HTTP clients.

### Outros HTTP clients

Vamos começar com `curl`, que é um HTTP client muito utilizado para testes e automação na linha de comando do terminal:

```bash
## Client
$ curl localhost:8080/ping
<p>Hello</p>
```

Interessante. Podemos ver que o programa `curl` sabe **interpretar uma mensagem HTTP**, mas *não sabe renderizar HTML* pois não é um Web browser.

Então é hora de testar no **browser**.

<figure><img src="/files/cAskzwwsFw8ZVJ26Blu1" alt=""><figcaption></figcaption></figure>

**Super** **Yay**! Por isto é chamado de **Web browser**, correto? Vamos também olhar o request que o browser mandou para o server:

```
GET / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8
Sec-GPC: 1
Accept-Language: en-GB,en
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
```

Podemos reparar que a mensagem HTTP request tem o mesmo padrão que estávamos utilizando, com a diferença que o web browser adiciona muito mais HTTP headers para um melhor controle entre client e server.

Basta um web server saber ler e lidar com tais HTTP headers, enviar outros headers relevantes de volta no response e pronto, temos uma melhor experiência de utilização para os usuários de websites, tudo contemplado no padrão HTTP!

### Estado da conexão no HTTP

Importante destacar que, até o momento, tudo o que temos visto foi uma mensagem caminhar do cliente para o servidor (request), outra mensagem caminhar do servidor para o client (response) e então o server terminar o processo.&#x20;

O quê está acontecendo com a conexão?

#### HTTP é stateless por padrão

Como HTTP se posiciona na camada de Aplicação do TCP/IP, a informação que cliente e servidor trocam está sendo transportada via TCP.&#x20;

Em cada comunicação request-response é criada uma nova conexão TCP. Com isso, quando um cliente faz um pedido HTTP qualquer ao servidor e este responde, a conexão é encerrada e não há qualquer estado HTTP entre diferentes conexões TCP.&#x20;

Podemos então resumir o fluxo:

1. Client inicia conexão TCP como server
2. Client envia um request HTTP através da conexão
3. Server recebe a mensagem, processa e envia uma resposta HTTP
4. Server encerra a conexão com o client

Entender este fluxo é importante para compreendermos as limitações do HTTP por ser **stateless** (sem estado). Em futuras seções, vamos explorar formas de mitigar esta limitação para que possamos simular uma característica *stateful* (com estado).
