requests-enhancer

A drop-in enhancement layer for the popular requests library. Adds automatic retry with exponential backoff, thread-safe LRU response caching, configurable rate limiting, and pagination helpers — with zero changes to your existing requests code.
Why requests-enhancer?
Writing robust HTTP client code means handling transient failures, avoiding hammering rate-limited APIs, caching expensive responses, and navigating paginated endpoints. requests-enhancer packages all of this into a single SmartSession class that works exactly like requests.Session.
Installation
pip install requests-enhancer
Quick Start
from requests_enhancer import SmartSession
session = SmartSession(retries=3, cache_ttl=60, rate_limit=10)
resp = session.get("https://api.example.com/users")
print(resp.json())
Features
| Automatic retry | Configurable attempts, exponential backoff, and status codes to retry |
| Response caching | Thread-safe LRU cache with per-entry TTL and explicit bypass |
| Rate limiting | Per-instance calls-per-second ceiling using a sliding-window limiter |
| Context manager | with SmartSession() as s: works out of the box |
| Pagination helper | paginate() generator for page- and cursor-based REST APIs |
| URL utilities | build_url, strip_auth, safe_json, is_json |
API Reference
SmartSession
SmartSession(
retries=3,
backoff=0.5,
status_forcelist=(429, 500, 502, 503, 504),
cache_ttl=None,
cache_maxsize=256,
rate_limit=None,
timeout=(5, 30),
)
All standard requests.Session methods are available: .get(), .post(), .put(), .delete(), .request().
Additional keyword argument on .request():
use_cache=True — set to False to bypass the response cache for a single request.
Examples
from requests_enhancer import SmartSession
session = SmartSession(retries=5, backoff=1.0, status_forcelist=(429, 500, 503))
resp = session.get("https://api.example.com/data")
session = SmartSession(cache_ttl=300, cache_maxsize=512)
resp1 = session.get("https://api.example.com/config")
resp2 = session.get("https://api.example.com/config")
fresh = session.get("https://api.example.com/config", use_cache=False)
session = SmartSession(rate_limit=2.0, retries=3)
for url in urls:
session.get(url)
with SmartSession(retries=3, cache_ttl=60) as s:
users = s.get("https://api.example.com/users").json()
posts = s.get("https://api.example.com/posts").json()
paginate(session, url, ...)
Generator that yields requests.Response objects across paginated API endpoints.
paginate(
session,
url,
params=None,
page_param="page",
per_page=100,
per_page_param="per_page",
max_pages=50,
)
from requests_enhancer import SmartSession, paginate
session = SmartSession(retries=3)
all_items = []
for resp in paginate(session, "https://api.example.com/items", per_page=50):
all_items.extend(resp.json())
print(f"Fetched {len(all_items)} items")
Pagination stops automatically when an empty page is returned, a non-OK status is received, or max_pages is reached.
URL and response utilities
from requests_enhancer import build_url, strip_auth, safe_json, is_json
build_url("https://api.example.com", "/v2/users", {"page": 1, "limit": 50})
strip_auth("https://alice:secret@api.example.com/data")
data = safe_json(response, default={})
if is_json(response):
data = response.json()
Comparison with plain requests
| Automatic retry | Manual HTTPAdapter setup | ✅ One parameter |
| Response caching | ❌ | ✅ Thread-safe LRU with TTL |
| Rate limiting | ❌ | ✅ Per-instance sliding window |
| Pagination | ❌ | ✅ paginate() generator |
| Context manager | ✅ | ✅ Inherited |
| Drop-in compatible | — | ✅ Same method signatures |
Development
git clone https://github.com/Hexa-devy/requests-enhancer.git
cd requests-enhancer
pip install -e ".[dev]"
pytest
Contributing
See CONTRIBUTING.md.
Changelog
See CHANGELOG.md.
License
MIT © Hexa-devy