Fundamentos de HTTP e Implementação de Servidor Web Estático em Python

Protocolo HTTP

URL (Localizador Uniforme de Recursos) define o endereço de recursos web. Processo de acesso:

  1. Navegador envia requisição HTTP
  2. Servidor procesa e retorna resposta

Estrutura da Requisição HTTP

Componente Formato
Linha de requisição Método URI Versão_HTTP
Cabeçalhos Parâmetros de controle
Linha vazia \r\n
Corpo Dados opcionais

Métodos principais:

  • GET: Solicita dados (sem corpo)
  • POST: Envia dados para processamento

Estrutura da Resposta HTTP

Componente Formato
Linha de status Versão_HTTP Código_Status Descrição
Cabeçalhos Metadados da resposta
Linha vazia \r\n
Corpo Conteúdo solicitado

Códigos de Status Comuns

Código Significado
200 Sucesso
400 Requisição inválida
404 Recurso não encontrado
500 Erro interno do servidor

Ferramentas de Desenvolvimento

  • Element: Isnpecionar/modificar HTML
  • Console: Executar JavaScript
  • Source: Depurar código
  • Network: Monitorar comunicação HTTP

Implementação de Servidor Web Estático

Servidor Python Integrado

python3 -m http.server 8080

Servidor Básico com Resposta Fixa

import socket

def iniciar_servidor():
    srv_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    srv_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    srv_sock.bind(('', 8080))
    srv_sock.listen(5)
    
    while True:
        cliente_sock, endereco = srv_sock.accept()
        requisicao = cliente_sock.recv(1024).decode()
        
        with open('pagina.html', 'rb') as arquivo:
            conteudo = arquivo.read()
        
        resposta = (
            "HTTP/1.1 200 OK\r\n"
            "Server: PyServ\r\n\r\n"
        ).encode() + conteudo
        
        cliente_sock.send(resposta)
        cliente_sock.close()

if __name__ == '__main__':
    iniciar_servidor()

Servidor com Resposta Dinâmica

import socket

def processar_requisicao(cliente_sock):
    dados = cliente_sock.recv(1024).decode()
    caminho = dados.split()[1] or '/index.html'
    
    try:
        with open(f'static{caminho}', 'rb') as f:
            conteudo = f.read()
        cabecalho = "HTTP/1.1 200 OK\r\nServer: PyServ\r\n\r\n"
    except Exception:
        cabecalho = "HTTP/1.1 404 Not Found\r\n\r\n"
        conteudo = b'Recurso nao encontrado'
    
    cliente_sock.send(cabecalho.encode() + conteudo)
    cliente_sock.close()

def principal():
    srv_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    srv_sock.bind(('', 8080))
    srv_sock.listen(5)
    
    while True:
        cliente, addr = srv_sock.accept()
        processar_requisicao(cliente)

if __name__ == '__main__':
    principal()

Versão com Concorrência

import socket
import threading

def responder_cliente(cliente_sock):
    requisicao = cliente_sock.recv(1024).decode()
    recurso = requisicao.split()[1] or '/index.html'
    
    try:
        with open(f'static{recurso}', 'rb') as f:
            payload = f.read()
        cabecalho_resposta = "HTTP/1.1 200 OK\r\nServer: Threaded\r\n\r\n"
    except FileNotFoundError:
        cabecalho_resposta = "HTTP/1.1 404 Not Found\r\n\r\n"
        payload = b'404 Recurso Inexistente'
    
    cliente_sock.send(cabecalho_resposta.encode() + payload)
    cliente_sock.close()

def principal():
    srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    srv.bind(('', 8080))
    srv.listen(10)
    
    while True:
        cliente, _ = srv.accept()
        thread = threading.Thread(target=responder_cliente, args=(cliente,))
        thread.start()

Abordagem Orientada a Objetos

import socket
import threading

class ServidorWeb:
    def __init__(self, porta):
        self.socket_servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket_servidor.bind(('', porta))
        self.socket_servidor.listen(10)
    
    def manipular_cliente(self, sock_cliente):
        dados = sock_cliente.recv(1024).decode()
        caminho = dados.split()[1] or '/index.html'
        
        try:
            with open(f'static{caminho}', 'rb') as f:
                conteudo = f.read()
            resposta = "HTTP/1.1 200 OK\r\nServer: OOP\r\n\r\n".encode() + conteudo
        except Exception:
            resposta = "HTTP/1.1 404 Not Found\r\n\r\n".encode() + b'Erro 404'
        
        sock_cliente.send(resposta)
        sock_cliente.close()
    
    def iniciar(self):
        while True:
            cliente, _ = self.socket_servidor.accept()
            thread = threading.Thread(target=self.manipular_cliente, args=(cliente,))
            thread.start()

if __name__ == '__main__':
    servidor = ServidorWeb(8080)
    servidor.iniciar()

Controle por Linha de Comando

import socket
import threading
import sys

class ServidorWebAvancado:
    # Implementação similar à classe anterior com parâmetro de porta

def principal():
    if len(sys.argv) != 2 or not sys.argv[1].isdigit():
        print("Uso: python servidor.py [PORTA]")
        return
    
    porta = int(sys.argv[1])
    servidor = ServidorWebAvancado(porta)
    servidor.iniciar()

if __name__ == '__main__':
    principal()

Tags: HTTP ServidorWeb Python socket threading

Publicado em 7-10 02:48