---
# System prepended metadata

title: 04 HTTP Server
tags: [web, day1]

---

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

# 04 HTTP Server

Ao invés de acessarmos diretamente o recurso que está no sistema de arquivos. ex: páginas HTML, precisamos da figura do HTTP server, ou web server, que vai servir de intermédio e garantir qua o acesso seja principalmente controlado, pois não queremos expor todos os arquivos para a web.


## Criando um server com socket

Da mesma maneira que criamos um client com socket podemos também abrir um socket do lado servidor

`server.py`
```python
import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 9000))
server.listen()

try:
    while True:
        client, address = server.accept()
        data = client.recv(5000).decode()
        print(data)

        client.sendall(
            "HTTP/1.0 200 OK\r\n<html><body>Hello World</body></html>\r\n\r\n".encode()
        )
        client.shutdown(socket.SHUT_WR)
except:
    server.close()
```
```
python server.py
```


Agora em outro terminal podemos rodar nosso client para se conectar a este server:


`http_client.py`
```python
import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("localhost", 9000))
cmd = "GET http://example.com/index.html HTTP/1.0\r\n\r\n".encode()
client.send(cmd)

while True:
    data = client.recv(512)
    if len(data) < 1:
        break
    print(data.decode(), end="")

client.close()
```
```
python http_client.py
```

Felizmente não precisamos criar servidores usando `socket` diretamente pois Python já oferece algumas abstrações como veremos a seguir.


## Python builtin server

O Python já tem um servidor HTTP integrado que é capaz de servir contéudo estático de qualquer diretório.

Na pasta onde o arquivo `pagina.html` está localizado:

```bash
python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/)
```

Ao abrir no navegador http://0.0.0.0:8000

No navegador:

```
Directory listing for /

    estilo.css
    pagina.html
    script.js
```

No terminal verá:

```bash
10.20.1.2 - - [09/May/2022 18:10:16] "GET / HTTP/1.1" 200 -
10.20.1.2 - - [09/May/2022 18:10:16] "GET /favicon.ico HTTP/1.1" 404 -
```

Ao clicar para acessar http://0.0.0.0:8000/pagina.html

No terminal verá
```bash
0.20.1.2 - - [09/May/2022 18:12:31] "GET /pagina.html HTTP/1.1" 200 -
10.20.1.2 - - [09/May/2022 18:12:31] "GET /estilo.css HTTP/1.1" 200 -
10.20.1.2 - - [09/May/2022 18:12:31] "GET /script.js HTTP/1.1" 200 -
```

As duas grandes vantagens de servir o conteúdo utilizando um servidor `HTTP` são:

- Expor apenas o conteúdo que desejar
- Obter log de acessos

## Outros servidores

Um dos principais servidores do mercado é o `Nginx` (Engine X) e ele é mais seguro e mais performático do que o servidor builtin do Python, porém é recomendado apenas para ambiente de produção.

É possivel rodar o nginx usando containers

```
sudo docker run --name docker-nginx -p 8000:80 -d -v $PWD:/usr/share/nginx/html nginx
```

E então acessar http://0.0.0.0:8000 

No navegador verá:
```bash
403 Forbidden
nginx/1.21.6
```

O Nginx não expoe os arquivos todos do sistema de arquivos e além disso
pode ser configurado para efetuar outros controles como por exemplo o controle de acesso por rede privada, senha, limitações de acesso etc...

Ao adicionar http://0.0.0.0:8000/pagina.html ao final da url o site funciona normalmente.


## Conclusão

Até aqui estamos servindo o que chamamos de arquivos estáticos, `html`, `css`, `js` e `imagens`, repare que não existe programação envolvida no lado servidor, o JS é computado apenas quando o conteúdo já está entregue ao navegador.

Agora vamos finalmente ao Python :)