Protocolo HTTP
URL (Localizador Uniforme de Recursos) define o endereço de recursos web. Processo de acesso:
- Navegador envia requisição HTTP
- 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()