⚖️ Старый vs Новый: HTTP в Python
⚡ Ключевые отличия
- urllib (старое) — стандартная библиотека Python, многословная, ручное управление кодировкой и JSON
- requests (новое) — чистый API, автоматический JSON, сессии, обработка ошибок
verify=Falseотключает проверку SSL — небезопасно, только для тестовых стендов- Прямой
assertв API-клиенте (из лекции) → в продакшн-коде лучшеraise_for_status()
1. urllib (встроенная) vs requests
До появления requests для HTTP-запросов использовали стандартные модули urllib.request и http.client. Это многословно и неудобно.
Старый подход — urllib (из лекции, устарело)
# Старый способ через urllib
import urllib.request
import json
url = "http://5.101.50.27:8000/company/list"
req = urllib.request.Request(url)
req.add_header("Accept", "application/json")
with urllib.request.urlopen(req) as response:
body = response.read()
data = json.loads(body.decode("utf-8"))
print(data[0]["name"]) # QA Студия 'ТестировщикЪ'
Современный подход — requests
# Современный способ через requests
import requests
url = "http://5.101.50.27:8000/company/list"
resp = requests.get(url)
data = resp.json()
print(data[0]["name"]) # QA Студия 'ТестировщикЪ'
Вывод:
requests — стандарт де-факто для HTTP в Python. Используй его для тестирования API.
2. POST без json= vs с json=
Старый подход — ручное кодирование
# Старый: нужно вручную сериализовать и указать Content-Type
import requests
import json
payload = json.dumps({"name": "Test", "description": "Desc"})
headers = {"Content-Type": "application/json"}
resp = requests.post(url, data=payload, headers=headers)
Современный — параметр json=
# Современный: requests делает всё сам
import requests
resp = requests.post(url, json={"name": "Test", "description": "Desc"})
# Content-Type: application/json выставляется автоматически
Важно:
data={"key": "val"} отправляет application/x-www-form-urlencoded (как HTML-форма). json={"key": "val"} отправляет application/json. Перепутать — классическая ошибка.
3. assert status_code vs raise_for_status()
Из лекции — assert в API-клиенте
# company_api.py — из лекции
def get_company_list(self):
resp = requests.get(self.url + "/company/list")
assert resp.status_code == 200, \
f"Ошибка: ожидался статус 200, получен {resp.status_code}"
return resp.json()
Современный — raise_for_status()
# company_api.py — производственный стиль
def get_company_list(self):
resp = requests.get(self.url + "/company/list")
resp.raise_for_status() # HTTPError при 4xx/5xx
return resp.json()
# В тесте можно ловить исключение:
# with pytest.raises(requests.HTTPError): ...
Подход из лекции (assert в API-клиенте) понятен для обучения. В production-коде предпочитают
raise_for_status() — это стандартный способ в экосистеме requests.
4. Передача токена: query-параметр vs заголовок
Из лекции — токен в query-параметре
# company_api.py — как в X-Clients API
def delete_company(self, company_id):
token = self.get_token()
url = f"{self.url}/company/{company_id}?client_token={token}"
resp = requests.delete(url)
return resp.json()
Современный стандарт — заголовок Authorization
# Стандарт Bearer Token (RFC 6750)
def delete_company(self, company_id, token):
headers = {"Authorization": f"Bearer {token}"}
resp = requests.delete(
f"{self.url}/company/{company_id}",
headers=headers
)
return resp.json()
⚠️ X-Clients API использует
client_token в query-параметре — это особенность конкретного сервиса. Стандартный подход (Bearer Token в заголовке) описан в RFC 6750. При работе с другими API всегда проверяй их документацию.
5. verify=False — небезопасная практика
Небезопасно — отключение SSL
# Никогда не делать в продакшн
resp = requests.get(url, verify=False)
# Предупреждение: InsecureRequestWarning
# Уязвимость: MITM-атаки
Правильно — передать CA-сертификат
# Для корпоративных сертификатов
resp = requests.get(url, verify="/path/to/ca-bundle.crt")
# Для публичных HTTPS — verify=True (по умолчанию)
resp = requests.get("https://api.example.com/users")
verify=False допустим только на тестовых стендах с самоподписанными сертификатами, где вы полностью контролируете окружение. В тестах против публичных или prod API всегда используй verify=True.