A utility belt for advanced users of python-requests
—
Helper functions for debugging HTTP requests and responses, constructing user-agent strings, enhanced URL encoding, and other common tasks for HTTP client development.
Tools for inspecting and debugging HTTP traffic by dumping request and response details.
def dump_response(response, request_prefix=b'< ', response_prefix=b'> ', data_array=None):
"""
Dump HTTP response details for debugging.
Parameters:
- response: Response object to dump
- request_prefix: bytes, prefix for request lines (default: b'< ')
- response_prefix: bytes, prefix for response lines (default: b'> ')
- data_array: bytearray, optional array to append dump data
Returns:
bytes: formatted dump of response
"""
def dump_all(response, request_prefix=b'< ', response_prefix=b'> '):
"""
Dump both request and response details.
Parameters:
- response: Response object to dump
- request_prefix: bytes, prefix for request lines (default: b'< ')
- response_prefix: bytes, prefix for response lines (default: b'> ')
Returns:
bytes: formatted dump of request and response
"""
class PrefixSettings:
"""
Settings for customizing dump output prefixes.
Parameters:
- request: bytes, prefix for request lines
- response: bytes, prefix for response lines
"""
def __init__(self, request, response): ...import requests
from requests_toolbelt.utils import dump_response, dump_all
# Basic response debugging
response = requests.get('https://httpbin.org/get?param=value')
print(dump_response(response).decode('utf-8'))
# Debug both request and response
response = requests.post(
'https://httpbin.org/post',
json={'key': 'value'},
headers={'Custom-Header': 'test'}
)
print(dump_all(response).decode('utf-8'))
# Custom prefixes for better readability
response = requests.get('https://httpbin.org/headers')
debug_output = dump_all(
response,
request_prefix=b'REQUEST: ',
response_prefix=b'RESPONSE: '
)
print(debug_output.decode('utf-8'))
# Save debug output to file
response = requests.get('https://api.example.com/data')
with open('debug_output.txt', 'wb') as f:
f.write(dump_all(response))
# Append to existing data
data_buffer = bytearray()
response1 = requests.get('https://httpbin.org/get')
response2 = requests.post('https://httpbin.org/post', data={'test': 'data'})
dump_response(response1, data_array=data_buffer)
dump_response(response2, data_array=data_buffer)
with open('combined_debug.txt', 'wb') as f:
f.write(data_buffer)Build standardized, informative user-agent strings for HTTP requests.
def user_agent(name, version, extras=None):
"""
Create internet-friendly user-agent string.
Parameters:
- name: str, application name (e.g., 'my-scraper')
- version: str, application version (e.g., '1.0.0')
- extras: list, additional components as (name, version) tuples
Returns:
str: formatted user-agent string
"""
class UserAgentBuilder:
"""
Builder class for constructing user-agent strings.
Parameters:
- name: str, application name
- version: str, application version
"""
def __init__(self, name, version): ...
def include_extras(self, extras):
"""
Add extra components to user-agent.
Parameters:
- extras: list of (name, version) tuples
Returns:
UserAgentBuilder: self for chaining
"""
def include_implementation(self):
"""
Include Python implementation details.
Returns:
UserAgentBuilder: self for chaining
"""
def include_system(self):
"""
Include system/platform information.
Returns:
UserAgentBuilder: self for chaining
"""
def build(self):
"""
Build the final user-agent string.
Returns:
str: complete user-agent string
"""import requests
from requests_toolbelt.utils import user_agent
from requests_toolbelt.utils.user_agent import UserAgentBuilder
# Simple user-agent
ua = user_agent('my-app', '2.1.0')
print(ua) # Output: my-app/2.1.0 CPython/3.9.0 Linux/5.4.0
# User-agent with extras
extras = [('requests', '2.28.0'), ('urllib3', '1.26.0')]
ua = user_agent('data-collector', '1.5.2', extras)
print(ua)
# Using builder for custom control
builder = UserAgentBuilder('web-scraper', '3.0.0')
ua = builder.include_extras([
('beautifulsoup4', '4.11.1'),
('lxml', '4.9.1')
]).include_implementation().include_system().build()
# Use with requests
session = requests.Session()
session.headers['User-Agent'] = user_agent('my-client', '1.0')
response = session.get('https://httpbin.org/user-agent')
print(response.json())
# Different user-agents for different services
github_ua = user_agent('github-client', '2.0', [('requests', '2.28.0')])
twitter_ua = user_agent('twitter-bot', '1.5', [('oauth', '1.1')])
github_session = requests.Session()
github_session.headers['User-Agent'] = github_ua
twitter_session = requests.Session()
twitter_session.headers['User-Agent'] = twitter_uaImproved URL encoding with better handling of lists and complex data structures.
def urlencode(query, doseq=False, safe='', encoding=None, errors=None, quote_via=quote_plus):
"""
Enhanced URL encoding with improved list handling.
Parameters:
- query: dict or list of tuples, data to encode
- doseq: bool, handle sequences in values
- safe: str, characters not to encode
- encoding: str, character encoding
- errors: str, error handling scheme
- quote_via: callable, quoting function
Returns:
str: URL-encoded string
"""from requests_toolbelt.utils.formdata import urlencode
import requests
# Enhanced list handling
data = {
'tags': ['python', 'http', 'requests'],
'categories': ['web', 'api'],
'user': 'john_doe'
}
# Standard encoding - lists become multiple parameters
encoded = urlencode(data, doseq=True)
print(encoded) # tags=python&tags=http&tags=requests&categories=web&categories=api&user=john_doe
# Use with requests
response = requests.get('https://api.example.com/search', params=encoded)
# Complex data structures
complex_data = {
'filters': {
'status': ['active', 'pending'],
'type': 'user'
},
'sort': 'created_date',
'limit': 50
}
# Flatten and encode complex structures
flat_data = []
for key, value in complex_data.items():
if isinstance(value, dict):
for subkey, subvalue in value.items():
full_key = f"{key}[{subkey}]"
if isinstance(subvalue, list):
for item in subvalue:
flat_data.append((full_key, item))
else:
flat_data.append((full_key, subvalue))
else:
flat_data.append((key, value))
encoded = urlencode(flat_data)
print(encoded)Legacy functions maintained for backward compatibility.
def get_encodings_from_content(content):
"""
Extract character encodings from HTML content.
Parameters:
- content: str, HTML content to analyze
Returns:
list: detected encodings
Note: Deprecated - use charset-normalizer or chardet instead
"""
def get_unicode_from_response(response):
"""
Extract unicode text from response.
Parameters:
- response: Response object
Returns:
str: decoded response text
Note: Deprecated - use response.text instead
"""import requests
from requests_toolbelt.utils import dump_all, user_agent
def debug_api_call(url, method='GET', **kwargs):
"""Helper function for debugging API calls."""
# Setup session with debugging
session = requests.Session()
session.headers['User-Agent'] = user_agent('debug-client', '1.0')
# Make request
response = session.request(method, url, **kwargs)
# Debug output
print("=" * 50)
print(f"DEBUG: {method} {url}")
print("=" * 50)
print(dump_all(response).decode('utf-8', errors='replace'))
print("=" * 50)
return response
# Usage
response = debug_api_call(
'https://httpbin.org/post',
method='POST',
json={'test': 'data'},
headers={'Custom-Header': 'debug-value'}
)
# Automated debugging for multiple requests
def debug_request_batch(requests_list):
"""Debug multiple requests and save output."""
with open('debug_batch.txt', 'w') as f:
for i, req in enumerate(requests_list):
f.write(f"\\n{'='*60}\\n")
f.write(f"REQUEST {i+1}: {req['method']} {req['url']}\\n")
f.write(f"{'='*60}\\n")
response = requests.request(**req)
debug_output = dump_all(response).decode('utf-8', errors='replace')
f.write(debug_output)
# Usage
requests_to_debug = [
{'method': 'GET', 'url': 'https://httpbin.org/get'},
{'method': 'POST', 'url': 'https://httpbin.org/post', 'json': {'key': 'value'}},
{'method': 'PUT', 'url': 'https://httpbin.org/put', 'data': 'test data'}
]
debug_request_batch(requests_to_debug)Install with Tessl CLI
npx tessl i tessl/pypi-requests-toolbelt