Components Overview
This page provides an overview of the major components in Request Forge and how they interact.
System Architecture
High-Level Architecture
┌─────────────────────────────────────────────────────────────┐
│ Application Code │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ Request Forge │
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────┐ │
│ │ Request │→ │ Hook │→ │ Auth │ │
│ │ Processing │ │ Pipeline │ │ Injection │ │
│ └────────────────┘ └────────────────┘ └──────────────┘ │
│ ↓ ↓ ↓ │
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────┐ │
│ │ Retry │ │ HTTP │ │ Response │ │
│ │ Logic │ │ Execution │ │ Processing │ │
│ └────────────────┘ └────────────────┘ └──────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ Token Management Layer │
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────┐ │
│ │ Token │ │ Token │ │ Token │ │
│ │ Manager │ │ Provider │ │ Storage │ │
│ └────────────────┘ └────────────────┘ └──────────────┘ │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ Multi-Step Authentication Pipeline │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Step 1 │ → │ Step 2 │ → │ Step 3 │ │
│ └────────┘ └────────┘ └────────┘ │
└────────────────────────┬────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────┐
│ External Services │
│ (Auth Servers, APIs, Token Endpoints) │
└─────────────────────────────────────────────────────────────┘
Core Components
HttpClient
Responsibility: Execute HTTP requests with retry logic and lifecycle hooks.
Key Features:
Thread-safe session management
Request/response/error hook execution
Authentication injection
Retry logic with multiple strategies
Concurrent request execution
Resource management
Dependencies:
HttpClientConfig- ConfigurationRetryStrategyInterface- Retry logicAuthHookInterface- AuthenticationRequestHookInterface- Request hooksResponseHookInterface- Response hooksErrorHookInterface- Error hooks
Interaction Diagram:
Application
↓
HttpClient.get('/users')
↓
┌─────────────────────────────────────┐
│ 1. Execute request hooks │
│ 2. Execute auth hook (inject token) │
│ 3. Execute HTTP request │
│ 4. Check for auth error (401) │
│ ├─ Yes → Refresh token & retry │
│ └─ No → Continue │
│ 5. Check for retryable error │
│ ├─ Yes → Retry with backoff │
│ └─ No → Continue │
│ 6. Execute response hooks │
│ 7. Return response │
└─────────────────────────────────────┘
Example:
config = HttpClientConfigBuilder().build()
client = HttpClient(config)
response = client.get('/users')
HttpClientConfig
Responsibility: Hold immutable configuration data.
Key Features:
Immutable (frozen dataclass)
Validation on creation
Default values
Type-safe attributes
Attributes:
base_url- Base URL for requestsdefault_timeout- Default timeoutdefault_headers- Default headersverify_ssl- SSL verificationretry_strategy- Retry strategy instanceauth_hook- Authentication hookrequest_hooks- Request hooks tupleresponse_hooks- Response hooks tupleerror_hooks- Error hooks tuple
Created via: HttpClientConfigBuilder
HttpClientConfigBuilder
Responsibility: Build HttpClientConfig using fluent interface.
Key Features:
Fluent API (method chaining)
Validation at build time
Sensible defaults
Helper methods for common configurations
Example:
config = (
HttpClientConfigBuilder()
.with_base_url('https://api.example.com')
.with_timeout(30.0)
.with_retry(max_retries=3)
.with_bearer_token('token')
.build()
)
Retry Components
RetryStrategyInterface
Responsibility: Define retry behavior.
Key Methods:
should_retry(context, exception)- Determine if should retryget_delay(context)- Calculate delay before retrymax_retries- Maximum retry attempts
Implementations:
NoRetryStrategy- No retriesSimpleRetryStrategy- Fixed delayExponentialBackoffRetryStrategy- Exponential backoff with jitterCircuitBreakerRetryStrategy- Circuit breaker pattern
Interaction:
Request fails
↓
RetryStrategy.should_retry(context, exception)
↓
if True:
delay = RetryStrategy.get_delay(context)
sleep(delay)
retry request
else:
raise MaxRetryException
Hook Components
Hook Pipeline
Responsibility: Execute hooks in order during request lifecycle.
Hook Types:
RequestHookInterface - Modify requests before sending
ResponseHookInterface - Process responses after receiving
ErrorHookInterface - Handle errors during lifecycle
AuthHookInterface - Manage authentication
Execution Flow:
Request initiated
↓
Execute request hooks (in order)
hook1.before_request()
hook2.before_request()
hook3.before_request()
↓
Execute auth hook
auth_hook.before_request()
↓
HTTP request sent
↓
Response received
↓
Execute response hooks (in order)
hook1.after_response()
hook2.after_response()
hook3.after_response()
↓
Return response
(On error)
↓
Execute error hooks (in order)
hook1.on_error()
hook2.on_error()
hook3.on_error()
Built-in Hooks
Request Hooks:
LoggingRequestHook- Log outgoing requestsCorrelationIdHook- Add correlation IDsAuthorizationHook- Dynamic authorization
Response Hooks:
LoggingResponseHook- Log incoming responsesRateLimitResponseHook- Parse rate limit headers
Error Hooks:
LoggingErrorHook- Log errors
Auth Hooks:
TokenAuthHook- Token-based auth with refreshApiKeyAuthHook- API key authBasicAuthHook- HTTP Basic authCompositeAuthHook- Combine multiple auth methods
Token Management Components
TokenManager
Responsibility: Manage token lifecycle with caching.
Key Features:
Automatic token caching
Thread-safe token refresh
Prevents concurrent fetches
Expiration handling
Dependencies:
TokenProviderInterface- Fetches tokensTokenStorageInterface- Stores tokens
Flow:
get_token()
↓
Check storage for cached token
↓
if cached and not expired:
return cached token
else:
↓
Lock (prevent concurrent fetches)
↓
Double-check cache
↓
if still need new token:
↓
provider.fetch_token() or provider.refresh_token()
↓
Store in cache
↓
Return new token
TokenProviderInterface
Responsibility: Fetch and refresh tokens.
Key Methods:
fetch_token()- Fetch new tokenrefresh_token(current)- Refresh existing tokenservice_name- Service identifier
Implementations:
ClientCredentialsTokenProvider- OAuth2 client credentialsPasswordGrantTokenProvider- OAuth2 password grantPipelineTokenProvider- Wraps multi-step pipelineCustom implementations
TokenStorageInterface
Responsibility: Store and retrieve tokens.
Key Methods:
get(key)- Retrieve tokenset(key, token)- Store tokendelete(key)- Delete tokenexists(key)- Check existence
Implementations:
InMemoryTokenStorage- In-memory storage (single process)DjangoCacheTokenStorage- Django cache (multi-process)Custom implementations (Redis, Memcached, etc.)
Storage Comparison:
Storage |
Scope |
Persistence |
Use Case |
|---|---|---|---|
InMemoryTokenStorage |
Single process |
Lost on restart |
Development, single-instance |
DjangoCacheTokenStorage |
Multi-process |
Depends on backend |
Production, multi-instance |
RedisTokenStorage |
Multi-process |
Persistent |
Production, high availability |
Multi-Step Authentication Components
TokenFetchPipeline
Responsibility: Execute multi-step token fetching with dependencies.
Key Features:
Dependency resolution
Per-step caching
Selective invalidation
Cascading invalidation
Dependencies:
TokenFetcherInterface- Individual fetch stepsTokenStorageInterface- Cache storage
Execution Flow:
pipeline.execute()
↓
For each step in order:
↓
Check cache
↓
if cached and valid:
Use cached token
else:
↓
Verify dependencies available
↓
Fetch new token (passing dependency tokens)
↓
Cache with step's TTL
↓
Add to context for next steps
↓
Return final token
Example:
Step 1: device_token (no deps)
→ Fetch → Cache (30 days)
↓
Step 2: app_token (depends on device_token)
→ Fetch using device_token → Cache (1 hour)
↓
Step 3: user_token (depends on app_token)
→ Fetch using app_token → Cache (15 min)
↓
Return user_token
TokenFetcherInterface
Responsibility: Fetch a single token in a pipeline step.
Key Methods:
fetch(context)- Fetch token with dependency contextname- Step namedepends_on- Dependency step namesttl- Cache TTL for this step
Implementations:
HeaderTokenFetcher- Extract from response headersBodyTokenFetcher- Extract from response body (JSON)Custom implementations
PipelineTokenProvider
Responsibility: Wrap TokenFetchPipeline as TokenProviderInterface.
Purpose: Allow pipeline to be used with TokenManager.
Example:
pipeline = TokenFetchPipeline(steps=[...], storage=storage)
provider = PipelineTokenProvider(pipeline, 'myapp')
token_manager = TokenManager(provider)
Data Models
HttpRequest
Responsibility: Represent an HTTP request (immutable).
Key Attributes:
method- HTTP methodurl- Request URLheaders- Request headersparams- Query parametersjson_data- JSON bodydata- Form datatimeout- Request timeout
Methods:
with_headers(headers)- Create copy with additional headersto_dict()- Convert to dictionaryto_curl()- Convert to cURL command
HttpResponse
Responsibility: Represent an HTTP response (immutable).
Key Attributes:
status_code- HTTP status codeheaders- Response headerscontent- Raw byteselapsed_ms- Request durationurl- Final URLrequest- Original request
Properties:
text- Decoded contentis_success- 2xx statusis_client_error- 4xx statusis_server_error- 5xx status
Methods:
json()- Parse JSONjson_or_none()- Safe JSON parse
RequestContext
Responsibility: Track request lifecycle state (mutable).
Key Attributes:
request- The HTTP requestattempt- Current attempt numbermax_retries- Maximum retriesmetadata- Additional context data
Methods:
increment_attempt()- Increment attempt counteris_retry- Check if retry
TokenData
Responsibility: Represent token data (immutable).
Key Attributes:
access_token- Token stringtoken_type- Token typeexpires_at- Expiration datetimerefresh_token- Refresh tokenscope- Token scope
Properties:
is_expired- Check expirationauthorization_header- Get header value
Methods:
from_response(data)- Create from API response
Component Interactions
Request Flow
Application
↓
client.get('/users')
↓
HttpClient
├─→ Request Hooks
│ └─→ Modify request
├─→ Auth Hook
│ ├─→ TokenManager.get_token()
│ │ ├─→ Check TokenStorage
│ │ └─→ TokenProvider.fetch_token() if needed
│ └─→ Inject token into headers
├─→ Execute HTTP request
├─→ Check response
│ ├─→ If 401: Refresh token & retry
│ └─→ If retryable: RetryStrategy determines retry
├─→ Response Hooks
│ └─→ Process response
└─→ Return HttpResponse
Token Management Flow
TokenAuthHook.before_request()
↓
TokenManager.get_token()
↓
Check TokenStorage
↓
if cached and valid:
return cached
else:
↓
TokenProvider.fetch_token()
↓
(If PipelineTokenProvider)
↓
TokenFetchPipeline.execute()
↓
For each step:
↓
TokenFetcher.fetch(context)
↓
HTTP request to auth endpoint
↓
Parse response
↓
Return TokenData
↓
Store in TokenStorage
↓
Return final token
↓
Store in TokenStorage
↓
Return token
Thread Safety
Thread-Safe Components:
HttpClient- Thread-local sessionsTokenManager- Locking for token refreshInMemoryTokenStorage- RLock for dictionary accessTokenFetchPipeline- Lock-free (relies on storage locking)
Not Thread-Safe (by design):
HttpRequest- Immutable (inherently thread-safe)HttpResponse- Immutable (inherently thread-safe)HttpClientConfig- Immutable (inherently thread-safe)TokenData- Immutable (inherently thread-safe)
See Thread Safety for detailed thread-safety analysis.
Extension Points
Applications can extend Request Forge by:
Custom Retry Strategies
class CustomRetryStrategy(RetryStrategyInterface): def should_retry(self, context, exception): ... def get_delay(self, context): ...
Custom Hooks
class CustomRequestHook(RequestHookInterface): def before_request(self, request, context): ...
Custom Token Providers
class CustomTokenProvider(TokenProviderInterface): def fetch_token(self): ... def refresh_token(self, current): ...
Custom Token Storage
class CustomTokenStorage(TokenStorageInterface): def get(self, key): ... def set(self, key, token): ...
Custom Token Fetchers
class CustomTokenFetcher(TokenFetcherInterface): def fetch(self, context): ...
See Also
Design Principles - Design principles
Thread Safety - Thread-safety design
Client API Reference - Client API
Token Manager API Reference - Token management API