Core Modules
HTTP Client Framework
The HTTP client framework provides both synchronous and asynchronous HTTP clients with built-in retry logic, circuit breakers, connection pooling, and statistics.
IHTTPClient (Protocol Interface)
- class hfortix_core.http.IHTTPClient(*args, **kwargs)[source]
Bases:
ProtocolProtocol defining the interface for HTTP clients used by FortiOS endpoints.
This protocol allows any class implementing these methods to be used as an HTTP client, enabling: - Custom HTTP client implementations - Easier testing with mock/fake clients - Support for both sync and async clients - Extension by library users
Method signatures support both synchronous (returning dict) and asynchronous (returning Coroutine) implementations. The return type is Union to accommodate both modes.
Implementations: - HTTPClient: Synchronous implementation using httpx.Client - AsyncHTTPClient: Asynchronous implementation using httpx.AsyncClient
Note
All methods should handle vdom=False to skip VDOM parameter in requests. The raw_json parameter controls whether full API response is returned (True) or just the results section (False, default).
- get(api_type, path, params=None, vdom=None, raw_json=False, unwrap_single=False, action=None)[source]
Perform GET request to retrieve resource(s) from the API.
- Parameters:
api_type (
str) – API category (e.g., ‘cmdb’, ‘monitor’, ‘log’, ‘service’)path (
str) – Endpoint path (e.g., ‘firewall/address’,'firewall/address/web-server')
params (
Optional[dict[str,Any]]) – Optional query parameters (filters, pagination, etc.)vdom (
Union[str,bool,None]) – Virtual domain name, or False to skip VDOM parameterraw_json (
bool) – If True, return full API response with metadata; ifFalse
results (return only)
unwrap_single (
bool) – If True and result is single-item list, return just the itemaction (
Optional[str]) – Special action parameter (e.g., ‘schema’, ‘default’)
- Returns:
API response (sync mode) or Coroutine[dict] (async mode)
- Return type:
- Example (Sync):
result = client.get(“cmdb”, “firewall/address/web-server”)
- Example (Async):
result = await client.get(“cmdb”, “firewall/address/web-server”)
- post(api_type, path, data, params=None, vdom=None, raw_json=False)[source]
Perform POST request to create new resource(s) in the API.
- Parameters:
api_type (
str) – API category (e.g., ‘cmdb’, ‘monitor’, ‘log’, ‘service’)path (
str) – Endpoint path (e.g., ‘firewall/address’)params (
Optional[dict[str,Any]]) – Optional query parametersvdom (
Union[str,bool,None]) – Virtual domain name, or False to skip VDOM parameterraw_json (
bool) – If True, return full API response with metadata; ifFalse
results (return only)
- Returns:
API response (sync mode) or Coroutine[dict] (async mode)
- Return type:
- Example (Sync):
result = client.post(“cmdb”, “firewall/address”, data={“name”: “test”, “subnet”: “10.0.0.1/32”})
- Example (Async):
result = await client.post(“cmdb”, “firewall/address”, data={…})
- put(api_type, path, data, params=None, vdom=None, raw_json=False)[source]
Perform PUT request to update existing resource in the API.
- Parameters:
api_type (
str) – API category (e.g., ‘cmdb’, ‘monitor’, ‘log’, ‘service’)path (
str) – Endpoint path with identifier (e.g.,'firewall/address/web-server')
params (
Optional[dict[str,Any]]) – Optional query parametersvdom (
Union[str,bool,None]) – Virtual domain name, or False to skip VDOM parameterraw_json (
bool) – If True, return full API response with metadata; ifFalse
results (return only)
- Returns:
API response (sync mode) or Coroutine[dict] (async mode)
- Return type:
- Example (Sync):
result = client.put(“cmdb”, “firewall/address/web-server”, data={“subnet”: “10.0.0.2/32”})
- Example (Async):
result = await client.put(“cmdb”, “firewall/address/web-server”, data={…})
- delete(api_type, path, params=None, vdom=None, raw_json=False)[source]
Perform DELETE request to remove resource from the API.
- Parameters:
api_type (
str) – API category (e.g., ‘cmdb’, ‘monitor’, ‘log’, ‘service’)path (
str) – Endpoint path with identifier (e.g.,'firewall/address/web-server')
params (
Optional[dict[str,Any]]) – Optional query parametersvdom (
Union[str,bool,None]) – Virtual domain name, or False to skip VDOM parameterraw_json (
bool) – If True, return full API response with metadata; ifFalse
results (return only)
- Returns:
API response (sync mode) or Coroutine[dict] (async mode)
- Return type:
- Example (Sync):
result = client.delete(“cmdb”, “firewall/address/web-server”)
- Example (Async):
result = await client.delete(“cmdb”, “firewall/address/web-server”)
- close()[source]
Close the HTTP client and release resources.
- Return type:
- Returns:
None (sync clients) or Coroutine[None] (async clients)
Optional method - not required for basic protocol compliance. Custom clients may implement this for resource cleanup.
- Example (Sync):
client.close()
- Example (Async):
await client.close()
- get_connection_stats()[source]
Get connection statistics.
Optional method - not required for basic protocol compliance. Returns statistics about HTTP connections if supported.
- get_operations()[source]
Get audit log of all API operations.
Optional method - not required for basic protocol compliance. Only available when operation tracking is enabled.
- get_write_operations()[source]
Get audit log of write operations (POST/PUT/DELETE).
Optional method - not required for basic protocol compliance. Only available when operation tracking is enabled.
- get_retry_stats()[source]
Get retry statistics and metrics.
Optional method - not required for basic protocol compliance. Only available when adaptive retry is enabled.
- get_circuit_breaker_state()[source]
Get current circuit breaker state and metrics.
Optional method - not required for basic protocol compliance. Only available when circuit breaker is enabled.
- get_health_metrics()[source]
Get health metrics and performance indicators.
Optional method - not required for basic protocol compliance. Only available when adaptive retry is enabled.
BaseHTTPClient (Base Client)
- class hfortix_core.http.BaseHTTPClient(url, verify=True, vdom=None, max_retries=3, connect_timeout=10.0, read_timeout=300.0, circuit_breaker_threshold=5, circuit_breaker_timeout=60.0, max_connections=100, max_keepalive_connections=20, adaptive_retry=False, retry_strategy='exponential', retry_jitter=False, read_only=False, audit_handler=None, audit_callback=None, user_context=None, rate_limit_calls_per_min=None, rate_limit_calls_per_5min=None, rate_limit_calls_per_hour=None, rate_limit_errors_per_min=None, rate_limit_errors_per_5min=None, rate_limit_errors_per_hour=None, rate_limit=False, rate_limit_strategy='queue', rate_limit_max_requests=100, rate_limit_window_seconds=60.0, rate_limit_queue_size=100, rate_limit_queue_timeout=30.0, rate_limit_queue_overflow='block', circuit_breaker=False, circuit_breaker_half_open_calls=3, circuit_breaker_auto_retry=False, circuit_breaker_max_retries=3, circuit_breaker_retry_delay=5.0)[source]
Bases:
objectBase class for HTTP clients with shared logic.
Provides: - Parameter validation - URL building - Retry statistics - Circuit breaker state management - Endpoint timeout configuration - Path normalization and encoding - Data sanitization
- Parameters:
url (str)
verify (bool)
vdom (Optional[str])
max_retries (int)
connect_timeout (float)
read_timeout (float)
circuit_breaker_threshold (int)
circuit_breaker_timeout (float)
max_connections (int)
max_keepalive_connections (int)
adaptive_retry (bool)
retry_strategy (str)
retry_jitter (bool)
read_only (bool)
audit_handler (Optional[Any])
audit_callback (Optional[Any])
rate_limit_calls_per_min (Optional[int])
rate_limit_calls_per_5min (Optional[int])
rate_limit_calls_per_hour (Optional[int])
rate_limit_errors_per_min (Optional[int])
rate_limit_errors_per_5min (Optional[int])
rate_limit_errors_per_hour (Optional[int])
rate_limit (bool)
rate_limit_strategy (str)
rate_limit_max_requests (int)
rate_limit_window_seconds (float)
rate_limit_queue_size (int)
rate_limit_queue_timeout (float)
rate_limit_queue_overflow (str)
circuit_breaker (bool)
circuit_breaker_half_open_calls (int)
circuit_breaker_auto_retry (bool)
circuit_breaker_max_retries (int)
circuit_breaker_retry_delay (float)
- __init__(url, verify=True, vdom=None, max_retries=3, connect_timeout=10.0, read_timeout=300.0, circuit_breaker_threshold=5, circuit_breaker_timeout=60.0, max_connections=100, max_keepalive_connections=20, adaptive_retry=False, retry_strategy='exponential', retry_jitter=False, read_only=False, audit_handler=None, audit_callback=None, user_context=None, rate_limit_calls_per_min=None, rate_limit_calls_per_5min=None, rate_limit_calls_per_hour=None, rate_limit_errors_per_min=None, rate_limit_errors_per_5min=None, rate_limit_errors_per_hour=None, rate_limit=False, rate_limit_strategy='queue', rate_limit_max_requests=100, rate_limit_window_seconds=60.0, rate_limit_queue_size=100, rate_limit_queue_timeout=30.0, rate_limit_queue_overflow='block', circuit_breaker=False, circuit_breaker_half_open_calls=3, circuit_breaker_auto_retry=False, circuit_breaker_max_retries=3, circuit_breaker_retry_delay=5.0)[source]
Initialize base HTTP client with shared configuration
- Parameters:
url (
str) – Base URL for the API (required)verify (
bool) – Enable SSL certificate verification (default: True)max_retries (
int) – Maximum retry attempts (default: 3)connect_timeout (
float) – Connection timeout in seconds (default: 10.0)read_timeout (
float) – Read timeout in seconds (default: 300.0)circuit_breaker_threshold (
int) – DEPRECATED - use circuit_breaker=Truecircuit_breaker_timeout (
float) – DEPRECATED - use circuit_breaker=Truemax_connections (
int) – Maximum concurrent connections (default: 100)max_keepalive_connections (
int) – Maximum keepalive connections (default: 20)adaptive_retry (
bool) – Enable adaptive retry with backpressure detection (default: False). Monitors response times and adjusts retry delays based on FortiGate health signals.retry_strategy (
str) – Retry backoff strategy - ‘exponential’ (default) or ‘linear’. Exponential: 1s, 2s, 4s, 8s, 16s, 30s. Linear: 1s, 2s, 3s, 4s, 5s.retry_jitter (
bool) – Add random jitter (0-25% of delay) to retry delays to prevent thundering herd problem when multiple clients retry simultaneously (default: False).read_only (
bool) – Enable read-only mode - simulate write operations without executing (default: False)audit_handler (
Optional[Any]) – Handler for audit logging (implements AuditHandler protocol). Essential for compliance.audit_callback (
Optional[Any]) – Custom callback function for audit logging. Alternative to audit_handler.user_context (
Optional[dict[str,Any]]) – Optional dict with user/application context to include in audit logs.rate_limit_calls_per_min (
Optional[int]) – Track calls per minute (tracking only)rate_limit_calls_per_5min (
Optional[int]) – Track calls per 5 minutes (tracking only)rate_limit_calls_per_hour (
Optional[int]) – Track calls per hour (tracking only)rate_limit_errors_per_min (
Optional[int]) – Track errors per minute (tracking only)rate_limit_errors_per_5min (
Optional[int]) – Track errors per 5 minutes (tracking only)rate_limit_errors_per_hour (
Optional[int]) – Track errors per hour (tracking only)Enforcement (# Rate Limiting)
rate_limit (
bool) – Enable rate limiting enforcement (default: False). When enabled, enforces request rate limits with queue.rate_limit_strategy (
str) – How to handle rate limit exceeded: “queue” - Queue requests (default) “drop” - Drop requests silently “raise” - Raise RateLimitExceededErrorrate_limit_max_requests (
int) – Max requests per window (default: 100)rate_limit_window_seconds (
float) – Time window in seconds (default: 60.0)rate_limit_queue_size (
int) – Max queued requests (default: 100)rate_limit_queue_timeout (
float) – Max wait time in queue (default: 30.0)rate_limit_queue_overflow (
str) – What to do when queue is full: “block” - Wait for space (default) “drop” - Drop request silently “raise” - Raise RateLimitQueueFullErrorBreaker (# Circuit)
circuit_breaker (
bool) – Enable circuit breaker (default: False). When disabled, no overhead. When enabled, trips open after consecutive failures to protect service.circuit_breaker_half_open_calls (
int) – Test calls in half-open state (default: 3)circuit_breaker_auto_retry (
bool) – When True, wait and retry instead of immediately raising CircuitBreakerOpenError (default: False)circuit_breaker_max_retries (
int) – Max auto-retry attempts when circuit open (default: 3)circuit_breaker_retry_delay (
float) – Seconds between auto-retry attempts (default: 5.0)
- Return type:
None
- configure_endpoint_timeout(endpoint_pattern, connect_timeout=None, read_timeout=None)[source]
Configure custom timeout for specific endpoints
- get_connection_stats()[source]
Get HTTP connection pool statistics (base implementation)
Base class provides minimal stats. Child classes override this to provide detailed connection pool metrics.
- Returns:
circuit_breaker_state: Current circuit breaker state
consecutive_failures: Number of consecutive failures
last_failure_time: Timestamp of last failure
- Return type:
Dictionary with basic connection statistics
Note
Child classes (HTTPClient, AsyncHTTPClient, etc.) override this to include additional metrics like active_requests, pool_exhaustion, etc.
Example
>>> stats = client.get_connection_stats() >>> if stats['circuit_breaker_state'] == 'open': ... print("Circuit breaker is open!")
- get_rate_limit_status()[source]
Get current rate limit tracking status
Returns detailed rate limit statistics including: - Call counts in different time windows (last min, 5min, hour) - Error counts in different time windows - Total calls and errors since client creation - Configured limits - Whether current usage is within limits
- Returns:
calls_last_min: API calls in last 60 seconds
calls_last_5min: API calls in last 300 seconds
calls_last_hour: API calls in last 3600 seconds
errors_last_min: Errors in last 60 seconds
errors_last_5min: Errors in last 300 seconds
errors_last_hour: Errors in last 3600 seconds
total_calls: Total API calls since creation
total_errors: Total errors since creation
limits: Dict of configured limits
within_limits: Boolean, True if all limits respected
- Return type:
Dictionary with rate limit statistics
Note
This is for monitoring only - does NOT enforce rate limits. Configure limits via rate_limit_* parameters in __init__().
Example
>>> client = HTTPClient( ... url="...", ... token="...", ... rate_limit_calls_per_min=100, ... rate_limit_calls_per_hour=1000 ... ) >>> status = client.get_rate_limit_status() >>> print(f"Calls/min: {status['calls_last_min']}/100") >>> print(f"Within limits: {status['within_limits']}")
HTTPClient (Synchronous FortiOS)
- class hfortix_core.http.HTTPClient(url, verify=True, token=None, username=None, password=None, vdom=None, max_retries=3, connect_timeout=10.0, read_timeout=300.0, user_agent=None, circuit_breaker_threshold=5, circuit_breaker_timeout=60.0, circuit_breaker_auto_retry=False, circuit_breaker_max_retries=3, circuit_breaker_retry_delay=5.0, max_connections=100, max_keepalive_connections=20, session_idle_timeout=300, read_only=False, track_operations=False, adaptive_retry=False, retry_strategy='exponential', retry_jitter=False, audit_handler=None, audit_callback=None, user_context=None, rate_limit_calls_per_min=None, rate_limit_calls_per_5min=None, rate_limit_calls_per_hour=None, rate_limit_errors_per_min=None, rate_limit_errors_per_5min=None, rate_limit_errors_per_hour=None, rate_limit=False, rate_limit_strategy='queue', rate_limit_max_requests=100, rate_limit_window_seconds=60.0, rate_limit_queue_size=100, rate_limit_queue_timeout=30.0, rate_limit_queue_overflow='block', circuit_breaker=False, circuit_breaker_half_open_calls=3)[source]
Bases:
BaseHTTPClientInternal HTTP client for FortiOS API requests (Sync Implementation)
Implements the IHTTPClient protocol for synchronous HTTP operations.
Handles all HTTP communication with FortiGate devices including: - Session management - Authentication headers - SSL verification - Request/response handling - Error handling - Automatic retry with exponential backoff - Context manager support (use with ‘with’ statement)
- Query Parameter Encoding:
The requests library automatically handles query parameter encoding: - Lists: Encoded as repeated parameters (e.g., [‘a’, ‘b’] → ?key=a&key=b) - Booleans: Converted to lowercase strings (‘true’/’false’) - None values: Should be filtered out before passing to params - Special characters: URL-encoded automatically
- Path Encoding:
Paths are URL-encoded with / and % as safe characters to prevent double-encoding of already-encoded components.
- Protocol Implementation:
This class implements the IHTTPClient protocol, allowing it to be used interchangeably with other HTTP client implementations (e.g., AsyncHTTPClient, custom user-provided clients).
This class is internal and not exposed to users directly, but users can provide their own IHTTPClient implementations to FortiOS.__init__().
- Parameters:
url (str)
verify (bool)
token (Optional[str])
username (Optional[str])
password (Optional[str])
vdom (Optional[str])
max_retries (int)
connect_timeout (float)
read_timeout (float)
user_agent (Optional[str])
circuit_breaker_threshold (int)
circuit_breaker_timeout (float)
circuit_breaker_auto_retry (bool)
circuit_breaker_max_retries (int)
circuit_breaker_retry_delay (float)
max_connections (int)
max_keepalive_connections (int)
read_only (bool)
track_operations (bool)
adaptive_retry (bool)
retry_strategy (str)
retry_jitter (bool)
audit_handler (Optional[Any])
audit_callback (Optional[Any])
rate_limit_calls_per_min (Optional[int])
rate_limit_calls_per_5min (Optional[int])
rate_limit_calls_per_hour (Optional[int])
rate_limit_errors_per_min (Optional[int])
rate_limit_errors_per_5min (Optional[int])
rate_limit_errors_per_hour (Optional[int])
rate_limit (bool)
rate_limit_strategy (str)
rate_limit_max_requests (int)
rate_limit_window_seconds (float)
rate_limit_queue_size (int)
rate_limit_queue_timeout (float)
rate_limit_queue_overflow (str)
circuit_breaker (bool)
circuit_breaker_half_open_calls (int)
- __init__(url, verify=True, token=None, username=None, password=None, vdom=None, max_retries=3, connect_timeout=10.0, read_timeout=300.0, user_agent=None, circuit_breaker_threshold=5, circuit_breaker_timeout=60.0, circuit_breaker_auto_retry=False, circuit_breaker_max_retries=3, circuit_breaker_retry_delay=5.0, max_connections=100, max_keepalive_connections=20, session_idle_timeout=300, read_only=False, track_operations=False, adaptive_retry=False, retry_strategy='exponential', retry_jitter=False, audit_handler=None, audit_callback=None, user_context=None, rate_limit_calls_per_min=None, rate_limit_calls_per_5min=None, rate_limit_calls_per_hour=None, rate_limit_errors_per_min=None, rate_limit_errors_per_5min=None, rate_limit_errors_per_hour=None, rate_limit=False, rate_limit_strategy='queue', rate_limit_max_requests=100, rate_limit_window_seconds=60.0, rate_limit_queue_size=100, rate_limit_queue_timeout=30.0, rate_limit_queue_overflow='block', circuit_breaker=False, circuit_breaker_half_open_calls=3)[source]
Initialize HTTP client
- Parameters:
url (
str) – Base URL for API (e.g., “https://192.0.2.10”)verify (
bool) – Verify SSL certificatestoken (
Optional[str]) – API authentication token (if using token auth)username (
Optional[str]) – Username for authentication (if using username/passwordauth)
password (
Optional[str]) – Password for authentication (if using username/passwordauth)
max_retries (
int) – Maximum number of retry attempts on transient failures(default (all API calls) –
connect_timeout (
float) – Timeout for establishing connection in seconds(default – 10.0)
read_timeout (
float) – Timeout for reading response in seconds (default:300.0)
user_agent (
Optional[str]) – Custom User-Agent header for identifying application inlogs. (include in audit) – If None, defaults to ‘hfortix/{version}’. Useful for multi-team environments and troubleshooting in production.
circuit_breaker_threshold (
int) – Number of consecutive failures before(default –
circuit_breaker_timeout (
float) – Seconds to wait before transitioning to(default – 60.0)
circuit_breaker_auto_retry (
bool) – Enable automatic retry when circuit(default – False). When enabled, waits circuit_breaker_retry_delay seconds between retries instead of immediately raising exception. Useful for long-running automation scripts. NOT recommended for tests or interactive use.
circuit_breaker_max_retries (
int) – Maximum retry attempts when(default –
circuit_breaker_retry_delay (
float) – Delay in seconds between retry(default – 5.0). This is separate from circuit_breaker_timeout, which controls when the circuit transitions from open to half-open.
max_connections (
int) – Maximum number of connections in the pool(default –
max_keepalive_connections (
int) – Maximum number of keepalive connections(default –
session_idle_timeout (
Union[int,float,None]) – For username/password auth only. Idle timeoutbefore (in seconds) – proactively re-authenticating (default: 300 = 5 minutes). This should match your FortiGate’s ‘config system global’ -> ‘remoteauthtimeout’ setting. Set to None to disable proactive re-authentication. Note: API token authentication is stateless and doesn’t use sessions.
read_only (
bool) – Enable read-only mode - simulate write operations(default – False)
track_operations (
bool) – Enable operation tracking - maintain audit log of(default – False)
adaptive_retry (
bool) – Enable adaptive retry with backpressure detection(default – False). When enabled, monitors response times and adjusts retry delays based on FortiGate health signals (slow responses, 503 errors). Increases retry delays when FortiGate is overloaded to prevent cascading failures.
retry_strategy (
str) – Retry backoff strategy - ‘exponential’ (default) or ‘linear’. Exponential: 1s, 2s, 4s, 8s, 16s, 30s. Linear: 1s, 2s, 3s, 4s, 5s. Use exponential for transient failures, linear for rate limiting.retry_jitter (
bool) – Add random jitter (0-25% of delay) to retry delays to prevent thundering herd problem when multiple clients retry simultaneously (default: False).audit_handler (
Optional[Any]) – Handler for audit logging (implements AuditHandlerprotocol). – Use built-in handlers: SyslogHandler, FileHandler, StreamHandler, CompositeHandler. Essential for compliance (SOC 2, HIPAA, PCI-DSS). Example: SyslogHandler(“siem.company.com:514”)
audit_callback (
Optional[Any]) – Custom callback function for audit logging. Alternative to audit_handler. Receives operation dict as parameter. Example: lambda op: send_to_kafka(op)user_context (
Optional[dict[str,Any]]) – Optional dict with user/application context tologs. – Example: {“username”: “admin”, “app”: “automation”, “ticket”: “CHG-12345”}
rate_limit_calls_per_min (int | None)
rate_limit_calls_per_5min (int | None)
rate_limit_calls_per_hour (int | None)
rate_limit_errors_per_min (int | None)
rate_limit_errors_per_5min (int | None)
rate_limit_errors_per_hour (int | None)
rate_limit (bool)
rate_limit_strategy (str)
rate_limit_max_requests (int)
rate_limit_window_seconds (float)
rate_limit_queue_size (int)
rate_limit_queue_timeout (float)
rate_limit_queue_overflow (str)
circuit_breaker (bool)
circuit_breaker_half_open_calls (int)
- Raises:
ValueError – If parameters are invalid or both token and
username/password provided –
- Return type:
None
- login()[source]
Authenticate using username/password and obtain session token
This method is called automatically if username/password are provided during initialization. Can also be called manually to re-authenticate.
- Raises:
ValueError – If username/password not configured
AuthenticationError – If login fails
- Return type:
- logout()[source]
Logout and invalidate session token
This method is called automatically when using context manager (with statement). Can also be called manually to explicitly logout.
Note
Only applicable when using username/password authentication. Token-based authentication doesn’t require logout.
- Return type:
- get_connection_stats()[source]
Get HTTP connection pool statistics
- Returns:
- Connection statistics including:
http2_enabled: Whether HTTP/2 is enabled
max_connections: Maximum number of connections allowed
max_keepalive_connections: Maximum keepalive connections
active_requests: Current number of active requests
total_requests: Total requests made since initialization
pool_exhaustion_count: Times pool reached capacity
circuit_breaker_state: Current circuit breaker state
consecutive_failures: Number of consecutive failures
- Return type:
Example
>>> stats = client.get_connection_stats() >>> print(f"Circuit breaker: {stats['circuit_breaker_state']}") >>> print(f"Active requests: {stats['active_requests']}")
- set_transaction(transaction_id)[source]
Set active transaction ID for automatic header injection.
When a transaction ID is set, all subsequent requests will automatically include the ‘X-TRANSACTION-ID’ header required by FortiOS batch transactions.
Examples
>>> # Start transaction >>> client.set_transaction(19) >>> # All requests now include X-TRANSACTION-ID: 19 >>> >>> # Clear transaction >>> client.set_transaction(None)
- inspect_last_request()[source]
Get details of last API request for debugging
- Returns:
- Request information including:
method: HTTP method used
endpoint: API endpoint path
params: Query parameters
response_time_ms: Response time in milliseconds
status_code: HTTP status code
error: Error message if no requests made
- Return type:
Example
>>> client.get("/api/v2/cmdb/firewall/address") >>> info = client.inspect_last_request() >>> print(f"Last request took {info['response_time_ms']:.2f}ms")
- request(method, api_type, path, data=None, params=None, vdom=None, raw_json=False, request_id=None, silent=False)[source]
Generic request method for all API calls
- Parameters:
method (
str) – HTTP method (GET, POST, PUT, DELETE)api_type (
str) – API type (cmdb, monitor, log, service)path (
str) – API endpoint path (e.g., ‘firewall/address’, ‘system/status’)data (
Optional[dict[str,Any]]) – Request body data (for POST/PUT)vdom (
Union[str,bool,None]) – Virtual domain (None=use default, or specify vdom name)raw_json (
bool) – If False (default), return only ‘results’ field. If True,response (return full)
request_id (
Optional[str]) – Optional correlation ID for tracking requests acrosslogs
silent (
bool) – If True, suppress error logging (for exists() checks)
- Returns:
If raw_json=False, returns response[‘results’] (or full response if no ‘results’ key)
If raw_json=True, returns complete API response with status, http_status, etc.
- Return type:
- get(api_type, path, params=None, vdom=None, raw_json=False, silent=False)[source]
GET request
- Parameters:
- Return type:
- get_binary(api_type, path, params=None, vdom=None)[source]
GET request returning binary data (for file downloads)
- post(api_type, path, data, params=None, vdom=None, scope=None, raw_json=False)[source]
POST request - Create new object
- Parameters:
- Return type:
- put(api_type, path, data, params=None, vdom=None, scope=None, raw_json=False)[source]
PUT request - Update existing object
- Parameters:
- Return type:
- delete(api_type, path, params=None, vdom=None, scope=None, raw_json=False)[source]
DELETE request - Delete object
- Parameters:
- Return type:
- static validate_mkey(mkey, parameter_name='mkey')[source]
Validate and convert mkey to string
- Parameters:
- Return type:
- Returns:
String representation of mkey
- Raises:
ValueError – If mkey is None, empty, or invalid
Example
>>> mkey = HTTPClient.validate_mkey(user_id, 'user_id')
- static validate_required_params(params, required)[source]
Validate that required parameters are present in params dict
- Parameters:
- Raises:
ValueError – If any required parameters are missing
- Return type:
Example
>>> HTTPClient.validate_required_params(data, ['name', 'type'])
- static validate_range(value, min_val, max_val, parameter_name='value')[source]
Validate that a numeric value is within a specified range
- Parameters:
- Raises:
ValueError – If value is outside the specified range
- Return type:
Example
>>> HTTPClient.validate_range(port, 1, 65535, 'port')
- static validate_choice(value, choices, parameter_name='value')[source]
Validate that a value is one of the allowed choices
- Parameters:
- Raises:
ValueError – If value is not in the allowed choices
- Return type:
Example
>>> HTTPClient.validate_choice(protocol, ['tcp', 'udp'], 'protocol')
- static build_params(**kwargs)[source]
Build parameters dict, filtering out None values
- Parameters:
**kwargs (
Any) – Keyword arguments to build params from- Return type:
- Returns:
Dictionary with None values removed
Example
>>> params = HTTPClient.build_params(format=['name'], datasource=True, other=None) >>> # Returns: {'format': ['name'], 'datasource': True}
- close()[source]
Close the HTTP session and release resources
If using username/password authentication, this will also logout to properly clean up the session.
- Return type:
- get_operations()[source]
Get audit log of all tracked API operations
Returns all tracked operations (GET/POST/PUT/DELETE) in chronological order. Only available when track_operations=True was passed to constructor.
- Returns:
timestamp: ISO 8601 timestamp
method: HTTP method (GET/POST/PUT/DELETE)
api_type: API type (cmdb/monitor/log/service)
path: API endpoint path
data: Request payload (for POST/PUT), None otherwise
status_code: HTTP response status code
vdom: Virtual domain (if specified)
read_only: False for executed operations; blocked operations
use blocked_by_read_only: True instead
- Return type:
List of operation dictionaries with keys
Example
>>> client = HTTPClient(url="https://192.0.2.10", token="...", track_operations=True) >>> client.post("cmdb", "/firewall/address", {"name": "test"}) >>> ops = client.get_operations() >>> print(ops[0]) { 'timestamp': '2024-12-20T10:30:15Z', 'method': 'POST', 'api_type': 'cmdb', 'path': '/firewall/address', 'data': {'name': 'test'}, 'status_code': 200, 'vdom': 'root', 'read_only': False }
- get_write_operations()[source]
Get audit log of write operations only (POST/PUT/DELETE)
Filters tracked operations to return only write operations, excluding GET requests.
- Return type:
- Returns:
List of write operation dictionaries (same format as get_operations())
Example
>>> client = HTTPClient(url="https://192.0.2.10", token="...", track_operations=True) >>> client.get("cmdb", "/firewall/address/test") # GET - excluded >>> client.post("cmdb", "/firewall/address", {"name": "test2"}) # POST - included >>> client.delete("cmdb", "/firewall/address/test") # DELETE - included >>> write_ops = client.get_write_operations() >>> len(write_ops) # Returns 2 (POST and DELETE only) 2
- static make_exists_method(get_method)[source]
Create an exists() helper that works with both sync and async modes.
This utility wraps a get() method and returns a function that: - Returns True if the object exists - Returns False if ResourceNotFoundError is raised - Returns False if response has error status (e.g., {‘status’: ‘error’}) - Works transparently with both sync and async clients
- Parameters:
- Return type:
- Returns:
A function that returns bool (sync) or Coroutine[bool] (async)
Example
HTTPClientJSONRPC (Synchronous JSON-RPC, FortiManager/FortiAnalyzer)
hfortix_core.HTTPClientFMG is a backwards-compatibility alias for
HTTPClientJSONRPC.
AsyncHTTPClient (Asynchronous)
- class hfortix_core.http.AsyncHTTPClient(url, verify=True, token=None, username=None, password=None, vdom=None, max_retries=3, connect_timeout=10.0, read_timeout=300.0, user_agent=None, circuit_breaker_threshold=5, circuit_breaker_timeout=60.0, circuit_breaker_auto_retry=False, circuit_breaker_max_retries=3, circuit_breaker_retry_delay=5.0, max_connections=100, max_keepalive_connections=20, session_idle_timeout=300.0, read_only=False, track_operations=False, adaptive_retry=False, retry_strategy='exponential', retry_jitter=False, audit_handler=None, audit_callback=None, user_context=None, rate_limit_calls_per_min=None, rate_limit_calls_per_5min=None, rate_limit_calls_per_hour=None, rate_limit_errors_per_min=None, rate_limit_errors_per_5min=None, rate_limit_errors_per_hour=None, rate_limit=False, rate_limit_strategy='queue', rate_limit_max_requests=100, rate_limit_window_seconds=60.0, rate_limit_queue_size=100, rate_limit_queue_timeout=30.0, rate_limit_queue_overflow='block', circuit_breaker=False, circuit_breaker_half_open_calls=3)[source]
Bases:
BaseHTTPClientInternal async HTTP client for FortiOS API requests (Async Implementation)
Implements the IHTTPClient protocol for asynchronous HTTP operations.
Async version of HTTPClient using httpx.AsyncClient. Handles all HTTP communication with FortiGate devices including: - Async session management - Authentication headers - SSL verification - Request/response handling - Error handling - Automatic retry with exponential backoff - Async context manager support (use with ‘async with’ statement)
- Protocol Implementation:
This class implements the IHTTPClient protocol, allowing it to be used interchangeably with other HTTP client implementations (e.g., HTTPClient, custom user-provided async clients). All methods return coroutines that must be awaited.
This class is internal and not exposed to users directly, but users can provide their own async IHTTPClient implementations to FortiOS.__init__().
- Parameters:
url (str)
verify (bool)
token (Optional[str])
username (Optional[str])
password (Optional[str])
vdom (Optional[str])
max_retries (int)
connect_timeout (float)
read_timeout (float)
user_agent (Optional[str])
circuit_breaker_threshold (int)
circuit_breaker_timeout (float)
circuit_breaker_auto_retry (bool)
circuit_breaker_max_retries (int)
circuit_breaker_retry_delay (float)
max_connections (int)
max_keepalive_connections (int)
session_idle_timeout (Optional[float])
read_only (bool)
track_operations (bool)
adaptive_retry (bool)
retry_strategy (str)
retry_jitter (bool)
audit_handler (Optional[Any])
audit_callback (Optional[Any])
rate_limit_calls_per_min (Optional[int])
rate_limit_calls_per_5min (Optional[int])
rate_limit_calls_per_hour (Optional[int])
rate_limit_errors_per_min (Optional[int])
rate_limit_errors_per_5min (Optional[int])
rate_limit_errors_per_hour (Optional[int])
rate_limit (bool)
rate_limit_strategy (str)
rate_limit_max_requests (int)
rate_limit_window_seconds (float)
rate_limit_queue_size (int)
rate_limit_queue_timeout (float)
rate_limit_queue_overflow (str)
circuit_breaker (bool)
circuit_breaker_half_open_calls (int)
- __init__(url, verify=True, token=None, username=None, password=None, vdom=None, max_retries=3, connect_timeout=10.0, read_timeout=300.0, user_agent=None, circuit_breaker_threshold=5, circuit_breaker_timeout=60.0, circuit_breaker_auto_retry=False, circuit_breaker_max_retries=3, circuit_breaker_retry_delay=5.0, max_connections=100, max_keepalive_connections=20, session_idle_timeout=300.0, read_only=False, track_operations=False, adaptive_retry=False, retry_strategy='exponential', retry_jitter=False, audit_handler=None, audit_callback=None, user_context=None, rate_limit_calls_per_min=None, rate_limit_calls_per_5min=None, rate_limit_calls_per_hour=None, rate_limit_errors_per_min=None, rate_limit_errors_per_5min=None, rate_limit_errors_per_hour=None, rate_limit=False, rate_limit_strategy='queue', rate_limit_max_requests=100, rate_limit_window_seconds=60.0, rate_limit_queue_size=100, rate_limit_queue_timeout=30.0, rate_limit_queue_overflow='block', circuit_breaker=False, circuit_breaker_half_open_calls=3)[source]
Initialize async HTTP client
- Parameters:
url (
str) – Base URL for API (e.g., “https://192.0.2.10”)verify (
bool) – Verify SSL certificatestoken (
Optional[str]) – API authentication token (if using token auth)username (
Optional[str]) – Username for authentication (if using username/passwordauth)
password (
Optional[str]) – Password for authentication (if using username/passwordauth)
max_retries (
int) – Maximum number of retry attempts on transient failures(default (all API calls) –
connect_timeout (
float) – Timeout for establishing connection in seconds(default – 10.0)
read_timeout (
float) – Timeout for reading response in seconds (default:300.0)
circuit_breaker_threshold (
int) – Number of consecutive failures before(default –
circuit_breaker_timeout (
float) – Seconds to wait before transitioning to(default – 30.0)
circuit_breaker_auto_retry (
bool) – When True, automatically wait and retrybreaker (when circuit) – opens instead of raising error immediately (default: False). WARNING: Not recommended for test environments - may cause long delays.
circuit_breaker_max_retries (
int) – Maximum number of auto-retry attemptsbreaker – opens (default: 3). Only used when circuit_breaker_auto_retry=True.
circuit_breaker_retry_delay (
float) – Delay in seconds between retry(default – 5.0). Separate from circuit_breaker_timeout, which controls when the circuit transitions from open to half-open.
max_connections (
int) – Maximum number of connections in the pool(default –
max_keepalive_connections (
int) – Maximum number of keepalive connections(default –
session_idle_timeout (
Optional[float]) – For username/password auth only. Idle timeoutbefore (in seconds) – proactively re-authenticating (default: 300 = 5 minutes). Set to None or False to disable. Note: Async client does not yet implement proactive re-auth; this parameter is accepted for API compatibility.
read_only (
bool) – Enable read-only mode - simulate write operations(default – False)
track_operations (
bool) – Enable operation tracking - maintain audit log of(default – False)
adaptive_retry (
bool) – Enable adaptive retry with backpressure detection(default – False). When enabled, monitors response times and adjusts retry delays based on FortiGate health signals (slow responses, 503 errors).
retry_strategy (
str) – Retry backoff strategy - ‘exponential’ (default) or ‘linear’. Exponential: 1s, 2s, 4s, 8s, 16s, 30s. Linear: 1s, 2s, 3s, 4s, 5s.retry_jitter (
bool) – Add random jitter (0-25% of delay) to retry delays to prevent thundering herd problem (default: False).audit_handler (
Optional[Any]) – Handler for audit logging (implements AuditHandlerprotocol). – Use built-in handlers: SyslogHandler, FileHandler, StreamHandler, CompositeHandler. Essential for compliance (SOC 2, HIPAA, PCI-DSS).
audit_callback (
Optional[Any]) – Custom callback function for audit logging. Alternative to audit_handler. Receives operation dict as parameter.user_context (
Optional[dict[str,Any]]) – Optional dict with user/application context tologs. (include in audit) – Example: {“username”: “admin”, “app”: “automation”, “ticket”: “CHG-12345”}
rate_limit (
bool) – Enable rate limiting with token bucket algorithm (default: False). When enabled, enforces request limits with configurable queue and overflow strategies. Zero overhead when disabled.rate_limit_strategy (
str) – Rate limiting strategy (default: “queue”). Currently only “queue” is supported - uses token bucket algorithm with FIFO queue for overflow handling.rate_limit_max_requests (
int) – Maximum requests allowed per window (default: 100). Controls token bucket capacity and refill rate (tokens/second = max_requests/window_seconds).rate_limit_window_seconds (
float) – Time window in seconds for rate limit (default: 60.0). Tokens refill at max_requests/window_seconds per second.rate_limit_queue_size (
int) – Maximum requests to queue when rate limit exceeded (default: 100). Set to 0 to disable queuing (requests dropped immediately with clear message).rate_limit_queue_timeout (
float) – Maximum seconds to wait in queue (default: 30.0). Raises RateLimitQueueTimeoutError if exceeded.rate_limit_queue_overflow (
str) –- Queue overflow strategy (default:
”block”):
”block”: Block/wait until space available (respects
queue_timeout) - “drop”: Drop the new request silently (return False) - “raise”: Raise RateLimitQueueFullError
circuit_breaker (
bool) – Enable circuit breaker pattern (default: False). When enabled, opens circuit after threshold failures to prevent cascading failures. Requires successful test requests in half-open state before closing. BREAKING CHANGE: Previously always enabled, now opt-in for zero overhead.circuit_breaker_half_open_calls (
int) – Number of successful requests required in half-open state before closing circuit (default: 3). Prevents premature closing on transient recovery.rate_limit_calls_per_min (int | None)
rate_limit_calls_per_5min (int | None)
rate_limit_calls_per_hour (int | None)
rate_limit_errors_per_min (int | None)
rate_limit_errors_per_5min (int | None)
rate_limit_errors_per_hour (int | None)
- Raises:
ValueError – If parameters are invalid or both token and
username/password provided –
- Return type:
None
- async login()[source]
Authenticate using username/password and obtain session token (async)
Must be called manually for async clients (cannot be called in __init__). Alternatively, use async context manager which handles login/logout automatically.
- Raises:
ValueError – If username/password not configured
AuthenticationError – If login fails
- Return type:
Example
>>> client = AsyncHTTPClient(url, username="admin", password="password") >>> await client.login()
- async logout()[source]
Logout and invalidate session token (async)
This method is called automatically when using async context manager. Can also be called manually to explicitly logout.
Note
Only applicable when using username/password authentication. Token-based authentication doesn’t require logout.
- Return type:
- get_connection_stats()[source]
Get HTTP connection pool statistics (async client)
- Returns:
- Connection statistics including:
http2_enabled: Whether HTTP/2 is enabled
max_connections: Maximum number of connections allowed
max_keepalive_connections: Maximum keepalive connections
active_requests: Current number of active requests
total_requests: Total requests made since initialization
pool_exhaustion_count: Times pool reached capacity
circuit_breaker_state: Current circuit breaker state
consecutive_failures: Number of consecutive failures
- Return type:
Example
>>> stats = client.get_connection_stats() >>> print(f"Circuit breaker: {stats['circuit_breaker_state']}") >>> print(f"Active requests: {stats['active_requests']}")
- inspect_last_request()[source]
Get details of last API request for debugging
- Returns:
- Request information including:
method: HTTP method used
endpoint: API endpoint path
params: Query parameters
response_time_ms: Response time in milliseconds
status_code: HTTP status code
error: Error message if no requests made
- Return type:
Example
>>> await client.get("/api/v2/cmdb/firewall/address") >>> info = client.inspect_last_request() >>> print(f"Last request took {info['response_time_ms']:.2f}ms")
- async request(method, api_type, path, data=None, params=None, vdom=None, raw_json=False, request_id=None)[source]
Generic async request method for all API calls
- Parameters:
method (
str) – HTTP method (GET, POST, PUT, DELETE)api_type (
str) – API type (cmdb, monitor, log, service)path (
str) – API endpoint pathdata (
Optional[dict[str,Any]]) – Request body data (for POST/PUT)raw_json (
bool) – If False, return only ‘results’ field. If True, returnresponse (full)
request_id (
Optional[str]) – Optional correlation ID for tracking requests
- Returns:
API response (results or full response based on raw_json)
- Return type:
- async get_binary(api_type, path, params=None, vdom=None)[source]
Async GET request returning binary data
- async post(api_type, path, data, params=None, vdom=None, raw_json=False)[source]
Async POST request - Create new object
- async put(api_type, path, data, params=None, vdom=None, raw_json=False)[source]
Async PUT request - Update existing object
- async delete(api_type, path, params=None, vdom=None, raw_json=False)[source]
Async DELETE request - Delete object
- static validate_required_params(params, required)[source]
Validate that required parameters are present
- static validate_range(value, min_val, max_val, parameter_name='value')[source]
Validate that a numeric value is within a specified range
- static validate_choice(value, choices, parameter_name='value')[source]
Validate that a value is one of the allowed choices
- async close()[source]
Close the async HTTP session and release resources
This method should be called to properly clean up resources when using AsyncHTTPClient. It ensures that all network connections and sessions are closed.
- Return type:
- Usage:
Call await client.close() when you are done with the client in
async mode. - Prefer using the async context manager (async with) for automatic cleanup.
Example
client = AsyncHTTPClient(…) try:
…
- finally:
await client.close()
- get_operations()[source]
Get audit log of all tracked API operations
Returns all tracked operations (GET/POST/PUT/DELETE) in chronological order. Only available when track_operations=True was passed to constructor.
- get_write_operations()[source]
Get audit log of write operations only (POST/PUT/DELETE)
Filters tracked operations to return only write operations, excluding GET requests.
- static make_exists_method(get_method)[source]
Create an exists() helper that works with both sync and async modes.
This utility wraps a get() method and returns a function that: - Returns True if the object exists - Returns False if ResourceNotFoundError is raised - Works transparently with both sync and async clients
- Parameters:
- Return type:
- Returns:
A function that returns bool (sync) or Coroutine[bool] (async)
Example
CloudHTTPClient (FortiCloud REST)
Used by hfortix-forticare and hfortix-fortiztp for
OAuth2-authenticated FortiCloud REST APIs.
- class hfortix_core.http.CloudHTTPClient(url, oauth_token, verify=True, max_retries=3, connect_timeout=10.0, read_timeout=300.0, circuit_breaker_threshold=5, circuit_breaker_timeout=60.0, max_connections=100, max_keepalive_connections=20, adaptive_retry=False, retry_strategy='exponential', retry_jitter=False, user_agent=None, read_only=False, track_operations=False, audit_handler=None, audit_callback=None, user_context=None, token_callback=None, rate_limit_calls_per_min=None, rate_limit_calls_per_5min=None, rate_limit_calls_per_hour=None, rate_limit_errors_per_min=None, rate_limit_errors_per_5min=None, rate_limit_errors_per_hour=None, rate_limit=False, rate_limit_strategy='queue', rate_limit_max_requests=100, rate_limit_window_seconds=60.0, rate_limit_queue_size=100, rate_limit_queue_timeout=30.0, rate_limit_queue_overflow='block', circuit_breaker=False, circuit_breaker_half_open_calls=3, circuit_breaker_auto_retry=False, circuit_breaker_max_retries=3, circuit_breaker_retry_delay=5.0)[source]
Bases:
BaseHTTPClientHTTP client for Fortinet Cloud APIs with OAuth 2.0 authentication.
Designed for cloud services like FortiCare Asset Management API v3, FortiCloud, and other OAuth-protected Fortinet cloud endpoints.
Key Differences from HTTPClient: - Uses OAuth 2.0 Bearer tokens (Authorization: Bearer <token>) - No API key authentication - No VDOM support - Cloud-specific error handling - Rate limiting aware (100/min, 1000/hour for FortiCare)
- Authentication:
The client expects an OAuth access token obtained from: https://customerapiauth.fortinet.com/api/v1/oauth/token
- Rate Limits (FortiCare Asset Management):
100 calls per minute
1000 calls per hour
10 errors per hour
Batch operations: max 10 units, max 5 errors per batch
Example
>>> client = CloudHTTPClient( ... url="https://support.fortinet.com", ... oauth_token="your_oauth_token_here" ... ) >>> response = client.get("/ES/api/registration/v3/products/list") >>> client.logout()
Note
The interface differs from HTTPClient — no vdom/api_type params, and methods return a response envelope dict rather than the raw JSON body.
- Parameters:
url (str)
oauth_token (str)
verify (bool)
max_retries (int)
connect_timeout (float)
read_timeout (float)
circuit_breaker_threshold (int)
circuit_breaker_timeout (float)
max_connections (int)
max_keepalive_connections (int)
adaptive_retry (bool)
retry_strategy (str)
retry_jitter (bool)
user_agent (Optional[str])
read_only (bool)
track_operations (bool)
audit_handler (Optional[Any])
audit_callback (Optional[Any])
token_callback (Optional[Callable[[], str]])
rate_limit_calls_per_min (Optional[int])
rate_limit_calls_per_5min (Optional[int])
rate_limit_calls_per_hour (Optional[int])
rate_limit_errors_per_min (Optional[int])
rate_limit_errors_per_5min (Optional[int])
rate_limit_errors_per_hour (Optional[int])
rate_limit (bool)
rate_limit_strategy (str)
rate_limit_max_requests (int)
rate_limit_window_seconds (float)
rate_limit_queue_size (int)
rate_limit_queue_timeout (float)
rate_limit_queue_overflow (str)
circuit_breaker (bool)
circuit_breaker_half_open_calls (int)
circuit_breaker_auto_retry (bool)
circuit_breaker_max_retries (int)
circuit_breaker_retry_delay (float)
- __init__(url, oauth_token, verify=True, max_retries=3, connect_timeout=10.0, read_timeout=300.0, circuit_breaker_threshold=5, circuit_breaker_timeout=60.0, max_connections=100, max_keepalive_connections=20, adaptive_retry=False, retry_strategy='exponential', retry_jitter=False, user_agent=None, read_only=False, track_operations=False, audit_handler=None, audit_callback=None, user_context=None, token_callback=None, rate_limit_calls_per_min=None, rate_limit_calls_per_5min=None, rate_limit_calls_per_hour=None, rate_limit_errors_per_min=None, rate_limit_errors_per_5min=None, rate_limit_errors_per_hour=None, rate_limit=False, rate_limit_strategy='queue', rate_limit_max_requests=100, rate_limit_window_seconds=60.0, rate_limit_queue_size=100, rate_limit_queue_timeout=30.0, rate_limit_queue_overflow='block', circuit_breaker=False, circuit_breaker_half_open_calls=3, circuit_breaker_auto_retry=False, circuit_breaker_max_retries=3, circuit_breaker_retry_delay=5.0)[source]
Initialize Cloud HTTP client.
- Parameters:
url (
str) – Base URL of the cloud service (e.g., “https://support.fortinet.com”)oauth_token (
str) – OAuth 2.0 Bearer token for authenticationverify (
bool) – Enable SSL certificate verification (default: True)max_retries (
int) – Maximum number of retry attempts (default: 3)connect_timeout (
float) – Connection timeout in seconds (default: 10.0)read_timeout (
float) – Read timeout in seconds (default: 300.0)circuit_breaker_threshold (
int) – Failures before circuit opens (default: 5)circuit_breaker_timeout (
float) – Circuit breaker timeout in seconds (default: 60.0)max_connections (
int) – Maximum number of connections (default: 100)max_keepalive_connections (
int) – Max keepalive connections (default: 20)adaptive_retry (
bool) – Enable adaptive retry based on response timesretry_strategy (
str) – ‘exponential’ or ‘linear’ backoffretry_jitter (
bool) – Add random jitter to retry delaysuser_agent (
Optional[str]) – Custom User-Agent header (optional)read_only (
bool) – Enable read-only mode - simulate write operations without executing (default: False)track_operations (
bool) – Enable operation tracking - maintain audit log of all API calls (default: False)audit_handler (
Optional[Any]) – Handler for audit logging (implements AuditHandler protocol)audit_callback (
Optional[Any]) – Custom callback function for audit logging (alternative to audit_handler)user_context (
Optional[dict[str,Any]]) – Optional dict with user/application context to include in audit logstoken_callback (
Optional[Callable[[],str]]) – Optional callback to get fresh token before each request (returns str) Useful with CloudSession to ensure token is valid before each requestrate_limit (
bool) – Enable rate limiting enforcement (default: False)rate_limit_strategy (
str) – ‘queue’, ‘drop’, or ‘raise’ (default: ‘queue’)rate_limit_max_requests (
int) – Max requests per window (default: 100)rate_limit_window_seconds (
float) – Time window in seconds (default: 60.0)rate_limit_queue_size (
int) – Max queue size (default: 100)rate_limit_queue_timeout (
float) – Max wait time in queue (default: 30.0)rate_limit_queue_overflow (
str) – ‘block’ or ‘drop’ on overflow (default: ‘block’)circuit_breaker (
bool) – Enable circuit breaker (default: False)circuit_breaker_half_open_calls (
int) – Calls to test in half-open state (default: 3)circuit_breaker_auto_retry (
bool) – Wait and retry instead of raising immediately when circuit breaker is open (default: False)circuit_breaker_max_retries (
int) – Max auto-retry attempts when circuit open (default: 3)circuit_breaker_retry_delay (
float) – Seconds between auto-retry attempts (default: 5.0)rate_limit_calls_per_min (int | None)
rate_limit_calls_per_5min (int | None)
rate_limit_calls_per_hour (int | None)
rate_limit_errors_per_min (int | None)
rate_limit_errors_per_5min (int | None)
rate_limit_errors_per_hour (int | None)
- Raises:
ValueError – If oauth_token is empty or invalid parameters
- Return type:
None
- get(path, params=None, timeout=None)[source]
Send GET request to cloud API.
- Parameters:
- Returns:
data: JSON response body
http_status_code: HTTP status code
response_time: Response time in seconds
request_info: Request metadata (method, url, params)
- Return type:
Response envelope containing
- Raises:
httpx.HTTPStatusError – For HTTP error responses
httpx.TimeoutException – If request times out
httpx.RequestError – For network errors
- post(path, data=None, params=None, timeout=None)[source]
Send POST request to cloud API.
- Parameters:
- Returns:
data: JSON response body
http_status_code: HTTP status code
response_time: Response time in seconds
request_info: Request metadata (method, url, params, data)
- Return type:
Response envelope containing
- Raises:
httpx.HTTPStatusError – For HTTP error responses
httpx.TimeoutException – If request times out
httpx.RequestError – For network errors
- put(path, data=None, params=None, timeout=None)[source]
Send PUT request to cloud API.
- Parameters:
- Returns:
data: JSON response body
http_status_code: HTTP status code
response_time: Response time in seconds
request_info: Request metadata (method, url, params, data)
- Return type:
Response envelope containing
- Raises:
httpx.HTTPStatusError – For HTTP error responses
httpx.TimeoutException – If request times out
httpx.RequestError – For network errors
- delete(path, params=None, timeout=None)[source]
Send DELETE request to cloud API.
- Parameters:
- Returns:
data: JSON response body
http_status_code: HTTP status code
response_time: Response time in seconds
request_info: Request metadata (method, url, params)
- Return type:
Response envelope containing
- Raises:
httpx.HTTPStatusError – For HTTP error responses
httpx.TimeoutException – If request times out
httpx.RequestError – For network errors
- get_operations()[source]
Get audit log of all tracked API operations.
Returns all tracked operations (GET/POST/PUT/DELETE) in chronological order. Only available when track_operations=True was passed to constructor.
- Returns:
timestamp: ISO 8601 timestamp
method: HTTP method (GET/POST/PUT/DELETE)
path: API endpoint path
data: Request payload (for POST/PUT), None otherwise
status_code: HTTP response status code
read_only_simulated: True if operation was simulated in read-only mode
- Return type:
List of operation dictionaries with keys
Example
>>> client = CloudHTTPClient( ... url="https://support.fortinet.com", ... oauth_token="...", ... track_operations=True ... ) >>> client.post("/api/v3/products/list", data={"serial_number": "FGT*"}) >>> ops = client.get_operations() >>> print(ops[0]) { 'timestamp': '2026-02-06T10:30:15Z', 'method': 'POST', 'path': '/api/v3/products/list', 'data': {'serial_number': 'FGT*'}, 'status_code': 200, 'read_only_simulated': False }
- get_write_operations()[source]
Get audit log of write operations only (POST/PUT/DELETE).
Filters tracked operations to return only write operations, excluding GET requests.
- Return type:
- Returns:
List of write operation dictionaries (same format as get_operations())
Example
>>> client = CloudHTTPClient( ... url="https://support.fortinet.com", ... oauth_token="...", ... track_operations=True ... ) >>> client.get("/api/v3/products/list") # GET - excluded >>> client.post("/api/v3/products/register", data={...}) # POST - included >>> client.delete("/api/v3/products/123") # DELETE - included >>> write_ops = client.get_write_operations() >>> len(write_ops) # Returns 2 (POST and DELETE only) 2
- get_connection_stats()[source]
Get connection pool statistics.
- Returns:
http2_enabled: Whether HTTP/2 is enabled
max_connections: Maximum allowed connections
max_keepalive_connections: Maximum keepalive connections
active_requests: Number of currently active requests
total_requests: Total number of requests made
client_active: Whether HTTP session is initialized
circuit_breaker_state: Current circuit breaker state
consecutive_failures: Number of consecutive failures
last_failure_time: Timestamp of last failure
- Return type:
Dictionary with connection pool metrics
Example
>>> client = CloudHTTPClient(url="https://support.fortinet.com", oauth_token="...") >>> stats = client.get_connection_stats() >>> print(f"Active: {stats['active_requests']}/{stats['max_connections']}") Active: 2/100
- inspect_last_request()[source]
Get detailed information about the last HTTP request/response.
Useful for debugging and understanding what was sent/received.
- Returns:
- method: HTTP method (GET/POST/PUT/DELETE)
endpoint: API endpoint path (without query string)
url: Full URL with query string
params: Query parameters
response_time_ms: Response time in milliseconds
status_code: HTTP status code (if response available)
Or {“error”: “…”} if no requests have been made yet.
- Return type:
Dictionary with last request details
Example
>>> client = CloudHTTPClient(url="https://support.fortinet.com", oauth_token="...") >>> client.get("/api/v3/products/list") >>> last = client.inspect_last_request() >>> print(f"Last request took {last['response_time_ms']}ms") Last request took 234.5ms
FortiCloudAuth (OAuth2 Authentication)
- class hfortix_core.http.FortiCloudAuth(api_id, password, client_id='assetmanagement', auth_url=None)[source]
Bases:
objectFortiCloud OAuth 2.0 Authentication Helper.
Handles OAuth token acquisition from FortiCloud authentication API for various Fortinet cloud services.
- Supported Services:
assetmanagement: FortiCare Asset Management
FortiManager: FortiManager Cloud
FortiAnalyzer: FortiAnalyzer Cloud
fortigatecloud: FortiGate Cloud
fortipresence: FortiPresence Cloud
And more…
Example
>>> from hfortix_core.http.oauth import FortiCloudAuth >>> >>> auth = FortiCloudAuth( ... api_id="your_api_id", ... password="your_password", ... client_id="assetmanagement" ... ) >>> token = auth.get_token() >>> print(f"Token: {token[:20]}...")
- DEFAULT_AUTH_URL = 'https://customerapiauth.fortinet.com/api/v1/oauth/token/'
- __init__(api_id, password, client_id='assetmanagement', auth_url=None)[source]
Initialize FortiCloud authentication helper.
- Parameters:
- Raises:
ValueError – If api_id or password is empty
- get_token(force_refresh=False)[source]
Get OAuth access token.
Requests a new OAuth token from FortiCloud authentication API. Caches the token for reuse unless force_refresh is True.
- Parameters:
force_refresh (
bool) – Force request new token even if cached (default: False)- Return type:
- Returns:
OAuth access token string
- Raises:
httpx.HTTPError – If authentication request fails
KeyError – If response doesn’t contain access_token
Example
>>> auth = FortiCloudAuth(api_id="...", password="...") >>> token = auth.get_token()
get_oauth_token
- hfortix_core.http.get_oauth_token(api_id, password, client_id='assetmanagement', auth_url=None)[source]
Convenience function to get OAuth token.
This is a simplified wrapper around FortiCloudAuth for one-time token acquisition without needing to manage the auth object.
- Parameters:
- Return type:
- Returns:
OAuth access token string
- Raises:
httpx.HTTPError – If authentication request fails
KeyError – If response doesn’t contain access_token
Example
>>> from hfortix_core.http.oauth import get_oauth_token >>> >>> token = get_oauth_token( ... api_id="your_api_id", ... password="your_password", ... client_id="assetmanagement" ... ) >>> print(f"Token: {token}")
Caching
TTLCache
readonly_cache
Logging
RequestLogger
log_operation
StructuredFormatter
TextFormatter
LogFormatter (Protocol)
LogRecord (TypedDict)
- class hfortix_core.logging.LogRecord[source]
Bases:
TypedDictType definition for structured log record data
- timestamp
ISO 8601 UTC timestamp
- level
Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
- logger
Logger name (e.g., “hfortix.http.client”)
- message
Log message
- request_id
Unique request identifier for correlation
- method
HTTP method (GET, POST, PUT, DELETE)
- endpoint
API endpoint path
- status_code
HTTP status code
- duration_s
Request duration in seconds
- duration_ms
Request duration in milliseconds
- vdom
FortiOS Virtual Domain
- event
Event type (request_start, request_completed, request_failed)
- error
Error message (if applicable)
- error_type
Exception class name
- attempt
Current retry attempt number
- max_attempts
Maximum retry attempts
- source
Source location (file, line, function)
Debugging
DebugSession
debug_timer
format_connection_stats
format_request_info
print_debug_info
DebugFormatter (Protocol)
DebugInfo (TypedDict)
- class hfortix_core.debug.DebugInfo[source]
Bases:
TypedDictType definition for comprehensive debug information
- last_request
Information about the last API request
- connection_stats
Connection pool statistics
- session_active
Whether a debug session is active
- capture_enabled
Whether response capture is enabled
SessionSummary (TypedDict)
- class hfortix_core.debug.SessionSummary[source]
Bases:
TypedDictType definition for debug session summary
- duration_seconds
Total session duration in seconds
- total_requests
Total number of requests made
- successful_requests
Number of successful requests
- failed_requests
Number of failed requests
- avg_response_time_ms
Average response time in milliseconds
- max_response_time_ms
Maximum response time in milliseconds
- min_response_time_ms
Minimum response time in milliseconds
- stats_delta
Change in connection stats during session
- initial_stats
Connection stats at session start
- final_stats
Connection stats at session end
Formatting
fmt Module
Data formatting utilities for FortiOS objects and data structures.
Provides simple, type-agnostic conversion functions that handle any input gracefully. Never raises exceptions - returns sensible defaults for edge cases.
- hfortix_core.fmt.to_json(data, indent=2, **kwargs)[source]
Convert any data to formatted JSON string.
Handles objects with __dict__, converts sets/tuples to lists, and uses str() fallback for non-serializable types.
- hfortix_core.fmt.to_csv(data, separator=', ')[source]
Convert any data to comma-separated string.
- Parameters:
- Return type:
- Returns:
Comma-separated string
Examples
>>> to_csv(['port1', 'port2', 'port3']) 'port1, port2, port3'
>>> to_csv({'x': 1, 'y': 2, 'z': 3}) 'x=1, y=2, z=3'
>>> to_csv('already a string') 'already a string'
>>> to_csv(None) ''
>>> to_csv([1, 2, 3], separator=' | ') '1 | 2 | 3'
>>> class Interface: ... def __init__(self): ... self.name = "port1" ... self.ip = "10.0.0.1" >>> to_csv(Interface()) 'name=port1, ip=10.0.0.1'
- hfortix_core.fmt.to_dict(data)[source]
Convert any data to dictionary.
Returns a dict with string keys for most inputs (objects, existing dicts), or integer keys for list/tuple inputs.
- Parameters:
data (
Any) – Any Python object to convert- Return type:
- Returns:
Dictionary representation of the data
Examples
>>> class Policy: ... def __init__(self): ... self.name = "Allow-All" ... self.action = "accept" >>> to_dict(Policy()) {'name': 'Allow-All', 'action': 'accept'}
>>> to_dict({'already': 'a dict'}) {'already': 'a dict'}
>>> to_dict([('a', 1), ('b', 2)]) {'a': 1, 'b': 2}
>>> to_dict(['x', 'y', 'z']) {0: 'x', 1: 'y', 2: 'z'}
>>> to_dict('simple string') {'value': 'simple string'}
>>> to_dict(None) {'value': None}
- hfortix_core.fmt.to_multiline(data, separator='\\n')[source]
Convert any data to newline-separated string.
- Parameters:
- Return type:
- Returns:
Newline-separated string
Examples
>>> print(to_multiline(['port1', 'port2', 'port3'])) port1 port2 port3
>>> print(to_multiline({'name': 'policy1', 'action': 'accept'})) name: policy1 action: accept
>>> to_multiline('already a string') 'already a string'
>>> to_multiline(None) ''
>>> class Policy: ... def __init__(self): ... self.name = "Allow-All" ... self.policyid = 1 >>> print(to_multiline(Policy())) name: Allow-All policyid: 1
- hfortix_core.fmt.to_list(data, delimiter=None)[source]
Convert any data to list.
- Parameters:
- Return type:
- Returns:
List representation of the data
Examples
>>> to_list(['already', 'a', 'list']) ['already', 'a', 'list']
>>> to_list(('tuple', 'to', 'list')) ['tuple', 'to', 'list']
>>> to_list({'a', 'b', 'c'}) # set to list ['a', 'b', 'c']
>>> to_list('port1,port2,port3', delimiter=',') ['port1', 'port2', 'port3']
>>> to_list('port1 port2 port3') # auto-splits on space ['port1', 'port2', 'port3']
>>> to_list('80 443 8080') # works with numbers as strings ['80', '443', '8080']
>>> to_list('port1 | port2 | port3', delimiter=' | ') ['port1', 'port2', 'port3']
>>> to_list('single_string') # no spaces, returns as-is ['single_string']
>>> to_list({'name': 'policy1', 'action': 'accept'}) ['policy1', 'accept']
>>> to_list(None) []
>>> to_list(42) [42]
>>> class Policy: ... def __init__(self): ... self.name = "Allow-All" ... self.policyid = 1 >>> to_list(Policy()) ['Allow-All', 1]
- hfortix_core.fmt.to_quoted(data, quote='"', separator=', ')[source]
Convert any data to quoted string representation.
- Parameters:
- Return type:
- Returns:
Quoted string representation
Examples
>>> to_quoted(['port1', 'port2', 'port3']) '"port1", "port2", "port3"'
>>> to_quoted({'x': 1, 'y': 2}) '"x", "y"'
>>> to_quoted('hello') '"hello"'
>>> to_quoted(None) '""'
>>> to_quoted([1, 2, 3], quote="'") "'1', '2', '3'"
>>> class Interface: ... def __init__(self): ... self.name = "port1" ... self.vlan = 10 >>> to_quoted(Interface()) '"name", "vlan"'
- hfortix_core.fmt.to_table(data, headers=True, delimiter=' | ')[source]
Convert data to table format.
- Parameters:
- Return type:
- Returns:
Table-formatted string
Examples
>>> policies = [ ... {'name': 'Allow-Web', 'action': 'accept', 'policyid': 1}, ... {'name': 'Block-All', 'action': 'deny', 'policyid': 2} ... ] >>> print(to_table(policies)) name | action | policyid Allow-Web | accept | 1 Block-All | deny | 2
>>> to_table(policies, headers=False) 'Allow-Web | accept | 1\nBlock-All | deny | 2'
>>> to_table(policies, delimiter=' || ') 'name || action || policyid\nAllow-Web || accept || 1\nBlock-All || deny || 2'
- hfortix_core.fmt.to_yaml(data, indent=2)[source]
Convert data to YAML-like format (simple, no external dependencies).
- Parameters:
- Return type:
- Returns:
YAML-style string
Examples
>>> policy = {'name': 'Allow-Web', 'action': 'accept', 'srcintf': ['port1', 'port2']} >>> print(to_yaml(policy)) name: Allow-Web action: accept srcintf: - port1 - port2
>>> print(to_yaml({'nested': {'key': 'value'}})) nested: key: value
- hfortix_core.fmt.to_xml(data, root='data', indent=2)[source]
Convert data to simple XML format (no external dependencies).
- Parameters:
- Return type:
- Returns:
XML string
Examples
>>> policy = {'name': 'Allow-Web', 'policyid': 1} >>> print(to_xml(policy, root='policy')) <policy> <name>Allow-Web</name> <policyid>1</policyid> </policy>
>>> policies = [{'name': 'p1'}, {'name': 'p2'}] >>> print(to_xml(policies, root='policies')) <policies> <item> <name>p1</name> </item> <item> <name>p2</name> </item> </policies>
- hfortix_core.fmt.to_key_value(data, separator='=', delimiter='\\n')[source]
Convert data to key=value pairs format.
- Parameters:
- Return type:
- Returns:
Key-value pairs string
Examples
>>> config = {'host': '192.168.1.1', 'port': 443, 'verify': False} >>> print(to_key_value(config)) host=192.168.1.1 port=443 verify=False
>>> to_key_value(config, separator=': ', delimiter='; ') 'host: 192.168.1.1; port: 443; verify: False'
- hfortix_core.fmt.to_markdown_table(data)[source]
Convert data to Markdown table format.
- Parameters:
data (
Any) – List of dicts or list of objects- Return type:
- Returns:
Markdown table string
Examples
>>> policies = [ ... {'name': 'Allow-Web', 'action': 'accept'}, ... {'name': 'Block-All', 'action': 'deny'} ... ] >>> print(to_markdown_table(policies)) | name | action | | --- | --- | | Allow-Web | accept | | Block-All | deny |
- hfortix_core.fmt.to_dictlist(data)[source]
Convert dict of lists to list of dicts (columnar to row format).
Useful for transforming columnar data into row-based records.
- Parameters:
data (
Any) – Dict where values are lists, or any convertible data- Return type:
- Returns:
List of dicts where each dict is one row
Examples
>>> columnar = {'name': ['p1', 'p2'], 'action': ['accept', 'deny']} >>> to_dictlist(columnar) [{'name': 'p1', 'action': 'accept'}, {'name': 'p2', 'action': 'deny'}]
>>> to_dictlist({'ports': ['80', '443', '8080']}) [{'ports': '80'}, {'ports': '443'}, {'ports': '8080'}]
>>> # Already list of dicts - returns as-is >>> to_dictlist([{'name': 'p1'}, {'name': 'p2'}]) [{'name': 'p1'}, {'name': 'p2'}]
>>> to_dictlist(None) []
- hfortix_core.fmt.to_listdict(data)[source]
Convert list of dicts to dict of lists (row to columnar format).
Useful for transforming row-based records into columnar data.
- Parameters:
data (
Any) – List of dicts, list of objects, or any convertible data- Return type:
- Returns:
Dict where keys are field names and values are lists
Examples
>>> rows = [{'name': 'p1', 'action': 'accept'}, {'name': 'p2', 'action': 'deny'}] >>> to_listdict(rows) {'name': ['p1', 'p2'], 'action': ['accept', 'deny']}
>>> to_listdict([{'ports': '80'}, {'ports': '443'}, {'ports': '8080'}]) {'ports': ['80', '443', '8080']}
>>> # Single dict becomes dict of single-item lists >>> to_listdict({'name': 'p1', 'action': 'accept'}) {'name': ['p1'], 'action': ['accept']}
>>> to_listdict(None) {}
Audit Logging
Enterprise-grade audit logging for compliance and security monitoring.
AuditHandler (Protocol)
SyslogHandler
FileHandler
StreamHandler
CompositeHandler
NullHandler
AuditFormatter (Protocol)
JSONFormatter
SyslogFormatter
CEFFormatter
AuditOperation (TypedDict)
Request Hooks
The hfortix_core.hooks module defines protocol classes
(BeforeRequestHook, AfterRequestHook, RequestContext) that are
reserved for a future request-interception feature. They are not yet
consumed by any HTTP client — passing hook objects to client constructors
has no effect in the current release.