Basic Usage
This guide covers the fundamental usage patterns of HTTP Client.
Making Requests
HTTP Client supports all standard HTTP methods.
GET Requests
Simple GET request:
from requestforge import create_client
client = create_client('https://api.example.com')
response = client.get('/users')
print(response.status_code) # 200
print(response.json()) # Parsed JSON response
GET with query parameters:
response = client.get('/users', params={
'page': 1,
'limit': 10,
'active': 'true'
})
# Requests: https://api.example.com/users?page=1&limit=10&active=true
GET with custom headers:
response = client.get('/users', headers={
'X-API-Version': '2.0',
'Accept-Language': 'en-US'
})
POST Requests
POST with JSON data:
response = client.post('/users', json_data={
'name': 'John Doe',
'email': 'john@example.com',
'age': 30
})
if response.status_code == 201:
created_user = response.json()
print(f"Created user ID: {created_user['id']}")
POST with form data:
response = client.post('/login', data={
'username': 'john',
'password': 'secret123'
})
POST with file upload:
response = client.post('/upload', files={
'file': open('document.pdf', 'rb'),
'thumbnail': open('thumb.jpg', 'rb')
})
PUT Requests
Update a resource:
response = client.put('/users/123', json_data={
'name': 'Jane Doe',
'email': 'jane@example.com'
})
PATCH Requests
Partial update:
response = client.patch('/users/123', json_data={
'email': 'newemail@example.com'
})
DELETE Requests
Delete a resource:
response = client.delete('/users/123')
if response.status_code == 204:
print("User deleted successfully")
Working with Responses
Response Object
Every request returns an HttpResponse object:
response = client.get('/users/1')
# Status code
print(response.status_code) # 200
# Headers
print(response.headers) # Dict of headers
print(response.headers['Content-Type']) # 'application/json'
# Body content
print(response.content) # bytes
print(response.text) # str
# Metadata
print(response.elapsed_ms) # Request duration in milliseconds
print(response.url) # Final URL after redirects
print(response.encoding) # Response encoding
Status Checks
Convenient properties for checking response status:
response = client.get('/users/1')
# Status categories
if response.is_success: # 2xx
print("Success!")
if response.is_client_error: # 4xx
print("Client error")
if response.is_server_error: # 5xx
print("Server error")
# Specific status codes
if response.status_code == 200:
print("OK")
elif response.status_code == 404:
print("Not found")
Parsing JSON
response = client.get('/users/1')
# Parse JSON (raises ResponseParseException on invalid JSON)
user = response.json()
print(user['name'])
# Safe JSON parsing (returns None on error)
data = response.json_or_none()
if data:
print(data['name'])
else:
print("Invalid JSON response")
Request Configuration
Per-Request Configuration
Override client defaults for specific requests:
from requestforge import HttpClient, HttpClientConfigBuilder
# Client with default timeout of 30s
config = HttpClientConfigBuilder().with_timeout(30.0).build()
client = HttpClient(config)
# Override timeout for this request only
response = client.get('/slow-endpoint', timeout=60.0)
# Override headers
response = client.get('/users', headers={
'X-Custom-Header': 'special-value'
})
Base URL Handling
Absolute vs. Relative URLs:
# With base URL
client = create_client('https://api.example.com')
# Relative URL (uses base URL)
response = client.get('/users')
# Requests: https://api.example.com/users
# Absolute URL (ignores base URL)
response = client.get('https://other-api.com/data')
# Requests: https://other-api.com/data
URL Construction:
# Leading/trailing slashes are handled automatically
client = create_client('https://api.example.com/')
# All of these work the same:
client.get('/users')
client.get('users')
client.get('/users/')
# All request: https://api.example.com/users
Using HttpRequest Objects
For more control, create HttpRequest objects explicitly:
from requestforge import HttpRequest, HttpMethod
request = HttpRequest(
method=HttpMethod.POST,
url='/users',
headers={'X-Custom': 'value'},
params={'notify': 'true'},
json_data={'name': 'John'},
timeout=60.0
)
response = client.request(request)
Modifying Requests:
# Create base request
request = HttpRequest(method=HttpMethod.GET, url='/users')
# Add headers (returns new request object)
authenticated_request = request.with_headers({
'Authorization': 'Bearer token123'
})
# Original request is unchanged (immutable)
print(request.headers) # None
print(authenticated_request.headers) # {'Authorization': 'Bearer token123'}
Converting to cURL:
request = HttpRequest(
method=HttpMethod.POST,
url='https://api.example.com/users',
headers={'Authorization': 'Bearer token'},
json_data={'name': 'John'}
)
# Generate cURL command for debugging
curl_command = request.to_curl()
print(curl_command)
# Output: curl -X 'POST' -H 'Authorization: Bearer token' --data '{"name": "John"}' 'https://api.example.com/users'
Resource Management
Using Context Managers
Always close clients to release resources:
# Automatic cleanup with context manager (recommended)
with create_client('https://api.example.com') as client:
response = client.get('/users')
users = response.json()
# Client automatically closed here
Manual Cleanup:
client = create_client('https://api.example.com')
try:
response = client.get('/users')
finally:
client.close()
Session Lifecycle
Understanding session lifecycle:
from requestforge import HttpClient, HttpClientConfigBuilder
config = HttpClientConfigBuilder().with_base_url('https://api.example.com').build()
client = HttpClient(config)
# Sessions are created lazily per thread
response1 = client.get('/users') # Creates session
response2 = client.get('/posts') # Reuses same session
# Connection pooling is automatic
# Multiple requests reuse connections
# Close to release all connections
client.close()
Best Practices
Use Context Managers
# Good ✅ with create_client('https://api.example.com') as client: response = client.get('/users') # Avoid ❌ client = create_client('https://api.example.com') response = client.get('/users') # Forgot to close!
Reuse Client Instances
# Good ✅ - Connection pooling benefits client = create_client('https://api.example.com') for user_id in range(1, 100): response = client.get(f'/users/{user_id}') client.close() # Avoid ❌ - Creates new connection for each request for user_id in range(1, 100): client = create_client('https://api.example.com') response = client.get(f'/users/{user_id}') client.close()
Check Response Status
# Good ✅ response = client.get('/users/1') if response.is_success: user = response.json() else: print(f"Error: {response.status_code}") # Avoid ❌ - Assumes success response = client.get('/users/1') user = response.json() # May fail if status is 404/500
Handle Exceptions
# Good ✅ from requestforge import TimeoutException, HttpClientException try: response = client.get('/users/1') except TimeoutException: print("Request timed out") except HttpClientException as e: print(f"Request failed: {e}")
Use Appropriate Timeouts
# Good ✅ - Different timeouts for different endpoints fast_response = client.get('/health', timeout=5.0) slow_response = client.get('/reports/generate', timeout=120.0)
Common Patterns
Pagination
def fetch_all_users(client):
page = 1
all_users = []
while True:
response = client.get('/users', params={'page': page, 'limit': 100})
if not response.is_success:
break
users = response.json()
if not users:
break
all_users.extend(users)
page += 1
return all_users
Batch Operations
def create_users_batch(client, users_data):
results = []
for user_data in users_data:
response = client.post('/users', json_data=user_data)
results.append({
'data': user_data,
'success': response.is_success,
'response': response.json() if response.is_success else None
})
return results
Download Files
def download_file(client, url, output_path):
response = client.get(url)
if response.is_success:
with open(output_path, 'wb') as f:
f.write(response.content)
return True
return False
Next Steps
Learn about Authentication for token management
Explore Retry Strategies for robust requests
Read Error Handling for exception handling
Check Concurrent Requests for parallel execution