--- tags: web,day1 robots: noindex, nofollow lang: pt-br --- https://github.com/rochacbruno/python-web-api/tree/main/docs # 03 Cliente Servidor No exemplo que fizemos anteriormente abrimos o arquivo `pagina.html` diretamente no navegador pois o navegador estava localizado no mesmo computador onde o arquivo está armazenado. Geralmente não é assim que as coisas funcionam na web, quase sempre teremos os arquivos em computadores remotos, os **servidores** e um outro computador que faz um **pedido** de um arquivo, o **cliente**. ## Proxy Reverso Além de ter o arquivo disponível para ser servido no sistema de arquivos do servidor (e.x: no HD) o computador servidor precisa de um software que controle o acesso aos arquivos, pois se simplesmente deixar a porta de acesso aberta livremente para qualquer pedido dos clientes poderia abrir brechas de segurança. Para controlar o acesso aos recursos internos existe um sistema chamado de **proxy**, neste caso especificamente um **proxy reverso** e existem várias tecnologias para fazer isso sendo as famosas o **Apache** e o **Nginx**, como esses programas fazem muito mais coisas do que apenas serem um proxy chamamos eles de **web servers**. ![](https://github.com/rochacbruno/python-web-api/raw/main/docs/day1/imgs/proxy_reverso.png) ## O protocolo HTTP No lado servidor teremos um **web server** como o **Nginx** ou **Apache** e no lado cliente teremos navegadores como **Firefox** ou **Chrome**. Para que todos esses programas consigam trocar informações de forma padronizada, no começo dos anos 90 foi criado um protocolo, um padrão de comunicação que todos os sistemas web seguem, o [HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP), HyperText Transfer Protocol (Protocolo de Transferência de Hiper Texto) e ele foi inicialmente pensado para suportar um texto no formato HTML, arquivos estáticos como css, js e imagens e também metadados que são informações que trafegam junto com os arquivos. O HTTP está baseado em 2 açoes principais. - **PEDIDO** (Request) - Um texto que especifica o pedido do cliente. - **RESPOSTA** (Response) - Um texto que contém a resposta do servidor. E organiza-se em uma série de **verbos**, que também são chamados de **métodos** e são palavras chave que determinam a natureza da ação que o cliente deseja executar no servidor. https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods - **GET** - O cliente quer **pegar** um arquivo que está no servidor. - **POST** - O cliente quer **enviar** um arquivo para o servidor. - **PUT** ou **PATCH** - O cliente quer **alterar** um arquivo que está no servidor. - **DELETE** - O cliente quer **apagar** um arquivo que está no servidor. > 99% de tudo o que fazemos na web está relacionado a estas operações, essas operações são chamadas geralmente pela sigla **CRUD** (Create, Read, Update, Delete) ### Request O navegador vai enviar ao servidor um texto como esse: ```http GET /pagina.html User-Agent: Firefox/100 Accept: */* ``` Detalhando: - Pedido **GET** para pegar o arquivo no caminho **/pagina.html**. - Cabeçalhos: - Informação sobre qual é o cliente, neste caso um navegador **Firefox**. - Informação sobre quais tipos de arquivo o cliente aceita, neste caso qualquer tipo, mas poderia ser `text/html` para ser mais especifico. Além de `User-Agent:` e `Accept:` várias outras informações podem ser enviadas e essas informações são chamadas de `HEADERS` (cabeçalho) > Repare na linha em branco no final, ela indica que o request terminou. #### Criando um HTTP client com Python ```py import socket client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect(('example.com', 80)) 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() ``` Felizmente não precisamos escrever sockets desta maneira em Python pois existem muitas bibliotecas que já fazem isso de maneira abstraida. Com biblioteca built-in ```py from urllib.request import urlopen result = urlopen("http://example.com/index.html") print(result.read().decode("utf-8")) ``` Com biblioteca externa ```py import requests result = requests.get("http://example.com/index.html") print(result.status_code) print(result.content) ``` > **NOTA** aconselho substituir `requests` por `httpx` sempre que possível. ### Response Quando o **web server** recebe este pedido ele processa as informações ali contidas e faz processamentos como por exemplo roteamento, validação, autenticação etc para finalmente ir ao sistema de arquivos e encontrar o arquivo a ser retornado. A resposta também será dada em forma de texto. ```html HTTP/2 200 Ok Server: Nginx Content-Type: text/html Date: 07 May 2022 00:40:25 GMT Content-Lenght: 140 <html> <head> <link rel="stylesheet" href="estilo.css"> </head> <body> ... <script type="application/javascript" src="script.js"></script> </body> </html> ``` Detalhando: - Resposta `HTTP/2` com status `200` ok - Cabeçalhos: - Nome do servidor - Tipo de conteúdo - Data de criação do conteúdo - Tamanho do conteúdo em bytes - Body: - O Hypertexto, neste caso HTML > **Detalhe**: O servidor responde apenas com o arquivo `pagina.html` e portanto o navegador na hora de processar este arquivo vai perceber que existe uma tag `<link>` apontando para o arquivo `estilo.css` e outra tag `<script>` apontando para o arquivo `script.js` e então mais 2 pedidos separados serão efetuados. ### Status codes Uma informação importantissima nas respostas HTTP é o código de estado, ou `status code`. É com esse código que podemos validar se seu tudo certo com o pedido que fizemos ao servidor. No exemplo anterior o código retornado foi `200 Ok` e existe uma lista de códigos divididos em 5 categorias. - **100-199** = Informativos. - **200-299** = Códigos de sucesso. - **300-399** = Redirecionamentos. - **400-499** = Algo errado no lado cliente ou o pedido foi mal feito. - **500-599** = Algo errado no lado servidor. Para ver a lista completa: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status ## Conclusão O objetivo do desenvolvimento web backend é acessar recursos disponíveis no servidor, processar e entregar ao cliente em formato de texto, para esta comunicação ocorrer de forma organizada seguimos um protocolo HTTP e um formato especifico de texto.