---
# System prepended metadata

title: 06 Formulários
tags: [web, day1]

---

---
tags: web,day1
robots: noindex, nofollow
lang: pt-br
---
https://github.com/rochacbruno/python-web-api/tree/main/docs

# 06 Formulários

Até aqui vimos o funcionamento de uma requisição `GET` com o objetivo **pegar** um recurso que está localizado no servidor.

Acontece que na web também temos a comunicação inversa, o cliente (navegador) pode enviar informações para o servidor e para isso precisamos utilizar uma estrutura de formulários do HTML.

Os formulários foram introduzidos no HTML para permitir o envio
de mensagens em páginas de contato, as páginas `contato.html` que tem
na maioria dos sites.

![](https://github.com/rochacbruno/python-web-api/raw/main/docs/day1/imgs/form.png)

Conforme a imagem acima, o primeiro passo que precisamos fazer é criar um formulário vazio para que o cliente possa preencher.


`contato.html`
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Contato</title>
</head>
<body>
    <form action="envia.py" method="post">
        <label for="nome">Nome:</label><br>
        <input type="text" name="nome" /><br>
        <label for="mensagem">Mensagem:</label><br>
        <textarea name="mensagem" cols="30" rows="5"></textarea><br>
        <input type="submit" value="Enviar">
    </form>
</body>
</html>
```

Acessamos a mesma pasta onde está o arquivo html e podemos servir com 

```bash
python -m http.server
```

Ao acessar http://localhost:8000/contato.html podemos preencher e enviar o formulário.

![](https://github.com/rochacbruno/python-web-api/raw/main/docs/day1/imgs/html_form.png)

Porém ao clicar em enviar veremos a seguinte mensagem de erro:

```bash
Error response

Error code: 501

Message: Unsupported method ('POST').

Error code explanation: HTTPStatus.NOT_IMPLEMENTED - Server does not support this operation.
```

E este será o output no log do servidor

```bash
10.20.58.74 - - [11/May/2022 18:25:58] "GET /contato.html HTTP/1.1" 200 -
10.20.58.74 - - [11/May/2022 18:28:40] code 501, message Unsupported method ('POST')
10.20.58.74 - - [11/May/2022 18:28:40] "POST /envia.py HTTP/1.1" 501 -
```

> **Calma**, está tudo bem! este erro era esperado.

O servidor que rodamos com `python -m http.server` não está preparado para receber requisições
do tipo `POST`, por padrão ele apenas entende `GET`.

## CGI

Common Gateway Interface é um protocolo de comunicação para servidores web, o `http.server` da forma como estamos rodando não tem suporte a CGI, precisamos adicionar o suporte a scripts CGI.

Passo 1 criamos uma pasta chamada `cgi-bin` (este nome é padrão do protocolo CGI, suportado por servidores como Apache, Cherokee etc) e nesta pasta podemos
colocar scripts CGI escritos em Python ou Perl.

```bash
# na mesma pasta onde está o contato.html
mkdir cgi-bin
```

Agora criamos um arquivo chamado `cgi-bin/envia.py` e neste script faremos o processamento dos dados vindos do formulário e a resposta será em forma de texto HTML.

```py
#!/usr/bin/env python
import cgi
form = cgi.FieldStorage()
nome = form.getvalue('nome')
mensagem  = form.getvalue('mensagem')

print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head>")
print("<title>Enviado</title>")
print("</head>")
print("<body>")
print("<h1>Enviado com sucesso!</h1>")
print(f"<h2>{nome} - {mensagem}</h2>")
print("</body>")
print("</html>")
```

Agora precisamos dar permissão de execução ao script acima

```bash
chmod +x cgi-bin/envia.py
```

Alteramos o form para submeter a `action` para o caminho do CGI

```html
<form action="/cgi-bin/envia.py" method="post">
```

E agora servimos novamente usando o argumento `--cgi`

```bash
python -m http.server --cgi
```

Agora sim podemos tentar novamente e enviar nossa mensagem.

Acesse http://localhost:8000/contato.html

![](https://github.com/rochacbruno/python-web-api/raw/main/docs/day1/imgs/html_form.png)

Preencha e clique no botão enviar!

![](https://github.com/rochacbruno/python-web-api/raw/main/docs/day1/imgs/cgi_success.png)

> **Atenção** repare que tem erros de encoding 😯, mas você já sabe o que fazer para corrigir não é?


Repare também que a URL final é `/cgi-bin/envia.py` 🤷 se você clicar para ver o código fonte, verá que é apenas HTML

```html
<html>
<head>
<title>Enviado</title>
</head>
<body>
<h1>Enviado com sucesso!</h1>
<h2>Bruno - OlÃ¡ estou testando o envio de mensagem.</h2>
</body>
</html>
```

## Conclusão

- A tag `<form>` no html estrutura os campos que pretendemos receber no backend
- O script em Python é executado pelo webserver que tem suporte a CGI
- No script podemos capturar os valores do formulário
- Neste ponto podemos fazer o que quiser, ex: enviar e-mail ou guardar em um banco de dados
- Todos os `prints` que fazemos no CGI são retornados para o cliente, a saida padrão é impressa no stream de response.

Parabéns você acabou de programar para web do mesmo modo que os entepassados faziam :) 

Agora vamos partir para uma abordagem um pouco mais moderna.