Vexfox 🦊
Deterministic HTTP interaction recording, sanitization, and replay for Python tests.
Version 0.1.0 — Initial Pre-Release
The Problem
Modern applications depend heavily on external HTTP APIs: payment gateways, auth providers, AI platforms, and microservices. When testing code that calls these services, developers commonly face three frustrating trade-offs:
- Live API calls: Flaky test suites, network latency, unpredictable external service outages, and rate limit exhaustion.
- Manual mocks (
unittest.mock): Tedious to write, prone to drift from real API behavior, and blind to actual HTTP protocol semantics. - Legacy record/replay tools: Often monkey-patch global sockets, accidentally persist raw API keys and authentication tokens into git-tracked fixture files, or fail when query parameters change ordering.
The Vexfox Solution
Vexfox captures real HTTP traffic directly at the transport layer, scrubs sensitive credentials in-memory before writing fixtures to disk, and deterministically replays recorded responses during automated test runs with strictly zero network access.
+-------------------------------------------+
| Your Application Code / Tests |
+-------------------------------------------+
|
(HTTPX Calls)
v
+-------------------------------------------------------------------------+
| VEXFOX |
| |
| [Record Mode] [Replay Mode] |
| 1. Pass through to real API 1. Normalize incoming |
| 2. Intercept response request |
| 3. Scrub auth headers, tokens, 2. Semantic matching |
| query secrets, JSON fields (method, URL, |
| 4. Atomically persist to disk query, JSON body) |
| 3. Return response |
| * STRICTLY OFFLINE * |
+-------------------------------------------------------------------------+
| |
v v
+-------------------+ +-------------------+
| Real External API | | Cassette Fixture |
+-------------------+ | (Sanitized JSON) |
+-------------------+
Key Features
- Zero Network Flakiness: In
RecordMode.REPLAY, Vexfox guarantees that zero outbound network requests can escape. - Pre-Persistence Redaction: Secrets (passwords, auth tokens, session cookies, API keys) are scrubbed before cassette files touch the filesystem.
- Semantic Request Matching: Matches HTTP requests by method, normalized URL, order-insensitive query parameters, and structural JSON bodies (whitespace and key-ordering independent).
- HTTPX Native: Deep integration with both
httpx.Clientandhttpx.AsyncClientvia clean transport wrappers without invasive global socket monkey-patching. - Isolated Concurrency: Test contexts are isolated per thread and task using
contextvars. - Pytest Plugin: First-class pytest fixture (
vexfox) with automatic context cleanup. - CLI Management Toolkit: Inspect, list, and validate recorded cassette fixtures right from the command line.
Installation
pip install vexfox
System Requirements
- Python:
>= 3.11 - HTTPX:
>= 0.25.0
Verified Quick Start
Synchronous Client
import httpx
import vexfox
# First run: records the live response to fixtures/users.json with credentials redacted.
# Subsequent runs: deterministically replays the recorded response completely offline.
with vexfox.use_cassette("fixtures/users.json"):
response = httpx.get("https://api.example.com/v1/users")
assert response.status_code == 200
Asynchronous Client
import httpx
import vexfox
async def test_async_service():
async with vexfox.use_cassette("fixtures/async_users.json"):
async with httpx.AsyncClient() as client:
response = await client.get("https://api.example.com/v1/users")
assert response.status_code == 200
Recording Modes
Configure recording behavior explicitly using RecordMode:
from vexfox import RecordMode, use_cassette
with use_cassette("fixtures/orders.json", mode=RecordMode.REPLAY):
...
| Mode | Semantics |
|---|---|
once (default) |
Records real interaction if cassette file does not exist; replays if it does. |
record |
Always makes real network requests and updates/overwrites cassette data. |
replay |
Strictly replays from existing cassette. Fails if cassette is missing or if an unrecorded request is made. Zero network calls allowed. |
none |
Passthrough mode. Makes real network requests without recording or intercepting. |
Security Boundaries & Redaction
Protecting sensitive credentials is a core design guarantee of Vexfox. Redaction is applied in-memory before writing to disk:
Default Scrubbed Targets
- Headers:
Authorization,Proxy-Authorization,Cookie,Set-Cookie,X-Api-Key,X-Auth-Token,ApiKey. - Query Parameters:
api_key,token,secret,password,access_token,auth,client_secret. - JSON Body Keys: Recursive traversal redacts
password,secret,api_key,token,client_secret,private_key,access_token. - Pattern Matching: High-entropy regex scanners identify and scrub Bearer tokens, OpenAI (
sk-...), Stripe (sk_live_...), JWT tokens, and AWS access keys (AKIA...). - Basic Auth URLs: URLs containing embedded credentials (
https://user:pass@host/) are scrubbed tohttps://user:[REDACTED]@host/.
Customizing Redaction Rules
from vexfox import VexfoxConfig, use_cassette
config = VexfoxConfig(
sensitive_headers={"x-organization-token", "x-internal-key"},
sensitive_query_params={"session_token"},
sensitive_body_keys={"ssn", "payment_method"},
redaction_marker="[REDACTED]",
)
with use_cassette("fixtures/custom_auth.json", config=config):
...
Request Matching & Diagnostics
When replaying, incoming requests are compared against recorded interactions using semantic rules:
- HTTP Method: Case-insensitive match (
GET,POST,PUT,DELETE, etc.). - Normalized URL: Normalizes scheme, port, and trailing slashes.
- Query Parameters: Order-insensitive comparison while preserving duplicate query parameters.
- Request Body:
- JSON (
application/json): Compared structurally. Key ordering, indentations, and whitespace formatting do not cause false mismatches. - Text / Binary: Byte-accurate matching.
- JSON (
- Headers (Optional): Specific header matching can be enabled via
match_headers=("content-type",).
Secret-Safe Diagnostics
If an incoming request does not match any interaction in the cassette, Vexfox produces a detailed diagnostic failure report without leaking any query secrets or token parameters:
vexfox.exceptions.RequestMismatchError: No matching recorded interaction found for request: POST https://api.example.com/items
Mismatch diagnostics:
- Interaction #1: JSON body mismatch at key 'role': expected 'member', got 'superadmin'
Recorded interactions in cassette:
* [1] POST https://api.example.com/items
Pytest Integration
Vexfox automatically registers a vexfox pytest fixture:
import httpx
def test_user_profile(vexfox):
with vexfox("fixtures/user_profile.json"):
response = httpx.get("https://api.example.com/profile")
assert response.status_code == 200
Command-Line Toolkit
Vexfox includes a command-line tool for inspecting and verifying cassette files:
# Verify environment and system readiness
vexfox doctor
# List recorded cassettes in a directory with interaction counts
vexfox list ./fixtures
# Inspect cassette interactions (status, methods, sanitized URLs)
vexfox inspect fixtures/users.json
# Validate cassette JSON schema integrity
vexfox validate fixtures/users.json
Supported Workflows & Known Boundaries
- Supported Clients: Currently targets HTTPX (
httpx.Clientandhttpx.AsyncClient). - Binary Payloads: Preserved accurately using base64 encoding with explicit
is_binarymetadata. - Multipart Uploads: Captured as binary payloads in the current release. Custom field-level multipart parsing and per-field masking is scheduled for v0.2.
- Cassette Format: Persists using standard JSON (Schema v1) with atomic file writes to prevent corrupted fixture files during interrupted test runs.
- No Global Monkey-Patching: Interception is handled cleanly via transport wrappers without altering Python's global
socketmodule.
Testing & Contributing
We welcome contributions! Please review CONTRIBUTING.md and SECURITY.md before submitting pull requests.
# Clone the repository
git clone https://github.com/TanishJain13/Vexfox.git
cd vexfox
# Install with test dependencies
pip install -e ".[test]"
# Run test suite
pytest
# Run linter and formatting checks
ruff check .
ruff format --check .
License
MIT License. See LICENSE for details.
Metadata
Release files for vexfox 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| vexfox-0.1.0.tar.gz | 32.3 kB | With provenance | Details for vexfox-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| vexfox-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for vexfox-0.1.0-py3-none-any.whl |
Total release size: 58.0 kB
Release files / vexfox-0.1.0.tar.gz
| Download URL | vexfox-0.1.0.tar.gz |
|---|---|
| Size | 32.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f329ba55feb68cb790d44791224b07235c84673774633aa9687dfdb8198ff6a6
|
|
BLAKE2b-256 checksum How to use checksums |
ff7c9672a24072d55c4b9fa69725fd545d16d57dbaa24ad63319331ad52782f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logRelease files / vexfox-0.1.0-py3-none-any.whl
| Download URL | vexfox-0.1.0-py3-none-any.whl |
|---|---|
| Size | 25.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3dc7e34d2371b7e834d1b4d423937311365bcdf044fb0cf1884d938acca50679
|
|
BLAKE2b-256 checksum How to use checksums |
8a065db8d351b64850ed590713af3da21d43f895a7d198d068e18fe2d11d2f44
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logSecurity for vexfox 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for vexfox-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.