Manipulação de Cabeçalhos HTTP (Headers)
Ao utilizar a biblioteca requests do Python, é fundamental compreender como interagir com os cabeçalhos das requisições. Ao instanciar uma sessão, podemos inspecionar e modificar as configurações padrão de forma centralizada.
import requests
# Inicializando a sessão
http_client = requests.Session()
# Inspecionando cabeçalhos padrão
print(http_client.headers)
# Saída esperada: {'User-Agent': 'python-requests/2.x.x', 'Accept-Encoding': 'gzip, deflate', ...}
# Iterando sobre as chaves e valores
for header_name in http_client.headers.keys():
print(f"Chave: {header_name}")
# Removendo e atualizando cabeçalhos
http_client.headers.pop('User-Agent', None)
custom_headers = {
'Origin': 'https://api.exemplo.com',
'Host': 'api.exemplo.com',
'Referer': 'https://exemplo.com/',
'User-Agent': 'CustomApp/1.0'
}
http_client.headers.update(custom_headers)
É importante notar que atualizar os cabeçalhos diretamente no objeto de sessão torna as alterações permanentes para todas as requisições subsequentes. Em contrapartida, passar o parâmetro headers no método de requisição afeta apenas aquela chamada específica.
Extração e Processamento de Cookies
A obtenção de cookies pode ser feita de várias formas, dependendo de como o servidor os retorna. O objeto de sessão armazena automaticamente os cookies, mas em alguns cenários, é necessário processar o cabeçalho Set-Cookie manualmente.
import json
import requests
class AuthManager:
def __init__(self):
self._session = requests.Session()
self._parsed_cookies = {}
self._base_headers = {'User-Agent': 'Mozilla/5.0'}
def perform_login(self, endpoint, credentials):
response = self._session.post(
endpoint,
data=json.dumps(credentials),
headers=self._base_headers
)
# Tentativa de obtenção via cookie jar da sessão
jar_cookies = self._session.cookies.get_dict()
# Fallback: parsing manual do cabeçalho Set-Cookie
set_cookie_header = response.headers.get("Set-Cookie", "")
if set_cookie_header and not jar_cookies:
for cookie_part in set_cookie_header.split(";"):
if "=" in cookie_part:
k, v = cookie_part.strip().split("=", 1)
self._parsed_cookies[k] = v
return self._parsed_cookies
return jar_cookies
# Uso
manager = AuthManager()
user_cookies = manager.perform_login(
"https://api.exemplo.com/auth",
{"user": "admin", "pass": "hash_senha"}
)
print(user_cookies)
Após extrair os cookies, frequentemente precisamos convertê-los para formatos específicos, como dicionários ou strings formatadas, para utilizá-los em requisições subsequentes.
import requests
from requests.utils import dict_from_cookiejar
def fetch_and_format_cookies(login_url, payload):
resp = requests.post(login_url, json=payload)
# Método A: Converter CookieJar para dicionário
cookie_dict = dict_from_cookiejar(resp.cookies)
# Método B: Concatenar em formato de string HTTP
cookie_str = "; ".join([f"{k}={v}" for k, v in resp.cookies.items()])
return cookie_dict, cookie_str
# Utilizando os cookies formatados
def access_protected_resource(data_url, cookies_dict, cookies_string):
# Uso via parâmetro cookies (aceita dict)
resp1 = requests.get(data_url, cookies=cookies_dict)
# Uso via cabeçalho manual
headers = {"Cookie": cookies_string}
resp2 = requests.get(data_url, headers=headers)
return resp1.text, resp2.text
Persistência de Estado e Reutilização de Sessões
Chamadas diretas com requests.get() ou requests.post() não mantêm o estado entre requisições. Para fluxos que exigem autenticação prévia, como operações financeiras ou consultas protegidas, é necessário gerenciar a sessão de forma adequada.
import logging
import requests
class ApiSessionManager:
def __init__(self):
self._http_session = requests.Session()
def execute(self, method, url, payload=None, timeout=15):
method = method.lower()
logging.info(f"Executando {method.upper()} em {url}")
if method == 'get':
result = self._http_session.get(url, params=payload, timeout=timeout)
elif method == 'post':
result = self._http_session.post(url, json=payload, timeout=timeout)
else:
raise ValueError("Método HTTP não suportado")
return result.json()
# Fluxo de autenticação e ação protegida
if __name__ == "__main__":
api = ApiSessionManager()
# 1. Login (a sessão armazena o cookie automaticamente)
api.execute('post', 'https://api.exemplo.com/v1/login', {'phone': '123456789', 'pwd': 'secret'})
# 2. Ação protegida (o cookie é enviado automaticamente pela sessão)
recharge_response = api.execute('post', 'https://api.exemplo.com/v1/recharge', {'amount': 50})
print(recharge_response)
Estratégias de Passagem de Sessão em Testes de API
Ao escrever testes de integração ou automação de APIs, é comum precisar passar o contexto de autenticação entre diferentes funções. Existem duas abordagens principais para lidar com esse cenário.
Abordagem 1: Extração e Injeção Manual de Cookies
Nesta abordagem, extraímos o dicionário de cookies da resposta de login e o injetamos explicitamente em cada requisição subsequente. A principal desvantagem é a verbosidade e a necessidade de re-executar o login ou gerenciar o token manualmente em cada chamada de função.
import json
import requests
def authenticate_user(base_url):
headers = {'Content-Type': 'application/json'}
body = json.dumps({"username": "tester", "password": "12345"})
response = requests.post(f"{base_url}/login", data=body, headers=headers)
return response.cookies.get_dict()
def fetch_user_profile(base_url, auth_cookies):
headers = {'Content-Type': 'application/json'}
body = json.dumps({"page": 1, "limit": 10})
# Injeção manual dos cookies
response = requests.post(f"{base_url}/profile", data=body, headers=headers, cookies=auth_cookies)
return response.json()
Abordagem 2: Compartilhamento do Objeto Session
A abordagem mais eficiente consiste em instanciar um objeto requests.Session() e compartilhá-lo entre as funções. Isso não apenas gerencia os cookies autoamticamente, mas também reutiliza a conexão TCP subjacente (Keep-Alive), resultando em ganhos significativos de performance ao enviar múltiplas requisições para o mesmo host.
import json
import requests
def authenticate_session(base_url, session_obj):
headers = {'Content-Type': 'application/json'}
body = json.dumps({"username": "tester", "password": "12345"})
response = session_obj.post(f"{base_url}/login", data=body, headers=headers)
return session_obj # Retorna a sessão já autenticada
def fetch_user_profile_with_session(base_url, session_obj):
headers = {'Content-Type': 'application/json'}
body = json.dumps({"page": 1, "limit": 10})
# A sessão cuida dos cookies automaticamente
response = session_obj.post(f"{base_url}/profile", data=body, headers=headers)
return response.json()