import requests
import time
from typing import Optional
def make_request(
url: str,
headers: dict,
payload: dict,
max_retries: int = 3,
retry_on: tuple = (429, 500, 503)
) -> Optional[dict]:
for attempt in range(max_retries):
try:
res = requests.post(url, headers=headers, json=payload, timeout=60)
if res.status_code in retry_on:
if res.status_code == 429:
# Respect Retry-After header
wait = int(res.headers.get("Retry-After", 60))
else:
# Exponential backoff for 5xx errors
wait = 2 ** attempt
if attempt < max_retries - 1:
print(f"Attempt {attempt+1} failed ({res.status_code}), waiting {wait}s...")
time.sleep(wait)
continue
res.raise_for_status()
return res.json()
except requests.Timeout:
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
continue
raise
return None