API Overview¶
httptap provides a clean Python API for programmatic use and extension. This page maps the public surface exported from the httptap package root; the linked pages drill into the core classes and the extensibility protocols.
Architecture¶
httptap is built around a modular architecture with clear, injectable interfaces:
┌─────────────────┐
│ CLI / Renderer │ wires Visualizers & Exporters
└────────┬────────┘
│
▼
┌─────────────────┐
│ HTTPTapAnalyzer│ ◄── main entry point
└────────┬────────┘
│ (injectable collaborators)
├─► DNS Resolver (Protocol)
├─► TLS Inspector (Protocol)
├─► Timing Collector (Protocol)
└─► Request Executor (Protocol)
Main entry point¶
from httptap import HTTPTapAnalyzer
analyzer = HTTPTapAnalyzer()
steps = analyzer.analyze_url("https://httpbin.io")
analyze_url also accepts keyword-only arguments for non-GET requests:
from httptap import HTTPTapAnalyzer
from httptap.constants import HTTPMethod
analyzer = HTTPTapAnalyzer(follow_redirects=True, timeout=10.0)
steps = analyzer.analyze_url(
"https://httpbin.io/post",
method=HTTPMethod.POST,
content=b'{"name": "John"}',
headers={"Content-Type": "application/json"},
)
HTTPTapAnalyzer ¶
HTTPTapAnalyzer(
*,
follow_redirects: bool = False,
timeout: float = DEFAULT_TIMEOUT_SECONDS,
http2: bool = True,
verify_ssl: bool = True,
ca_bundle_path: str | None = None,
max_redirects: int = 10,
request_executor: RequestExecutor | None = None,
proxy: ProxyTypes | None = None,
noproxy: bool = False,
dns_resolver: DNSResolver | None = None,
tls_inspector: TLSInspector | None = None,
timing_collector_factory: type[TimingCollector]
| None = None,
)
Orchestrates HTTP request analysis with redirect following.
This class manages the high-level flow of analyzing HTTP requests, including following redirect chains and collecting metrics at each step.
属性:
-
follow_redirects–Whether to follow HTTP redirects.
-
timeout–Request timeout in seconds.
-
http2–Whether to enable HTTP/2 support.
-
max_redirects–Maximum number of redirects to follow.
参数:
-
follow_redirects(bool, 默认:False) –Whether to follow 3xx redirects.
-
timeout(float, 默认:DEFAULT_TIMEOUT_SECONDS) –Request timeout in seconds.
-
http2(bool, 默认:True) –Enable HTTP/2 support.
-
verify_ssl(bool, 默认:True) –Whether to verify TLS certificates.
-
ca_bundle_path(str | None, 默认:None) –Path to custom CA certificate bundle (PEM format). Only used when verify_ssl is True. If None, uses system CA bundle.
-
max_redirects(int, 默认:10) –Maximum number of redirects to follow.
-
request_executor(RequestExecutor | None, 默认:None) –Object responsible for performing HTTP requests. Must implement the RequestExecutor protocol. Defaults to the built-in httpx implementation.
-
proxy(ProxyTypes | None, 默认:None) –Optional proxy URL (http/https/socks5/socks5h) applied to all requests in the analysis chain.
-
noproxy(bool, 默认:False) –When True, ignore proxy environment variables and connect directly. Triggered by --proxy "".
-
dns_resolver(DNSResolver | None, 默认:None) –Custom DNS resolver implementation. If None, make_request will use its default (SystemDNSResolver).
-
tls_inspector(TLSInspector | None, 默认:None) –Custom TLS inspector implementation. If None, make_request will use its default (SocketTLSInspector).
-
timing_collector_factory(type[TimingCollector] | None, 默认:None) –Factory class for creating timing collectors. If None, make_request will use its default (PerfCounterTimingCollector). Note: This should be a class, not an instance, as a new collector is created for each request.
源代码位于: httptap/analyzer.py
See Core Components for the full method and data-model reference.
Core data model¶
A single request/response cycle is captured by StepMetrics, which nests timing, network, and response detail. Full field-level docs live on the Core Components page.
StepMetrics— one request in a redirect chainTimingMetrics— phase-by-phase timingNetworkInfo— IP, TLS, certificate, and proxy detailResponseInfo— status, headers, body size
Protocol interfaces¶
httptap uses Protocol classes (PEP 544) for type-safe, inheritance-free extensibility. Each protocol and a worked custom implementation is documented on the Protocol Interfaces page: DNSResolver, TLSInspector, TimingCollector, Visualizer, Exporter, and RequestExecutor.
Request executor¶
For fully customised HTTP behaviour, implement the RequestExecutor protocol and pass an instance as request_executor= to HTTPTapAnalyzer. The protocol contract and its RequestOptions / RequestOutcome data classes are documented on the Protocol Interfaces page.
Built-in implementations¶
httptap ships production-ready defaults for every protocol; all are importable from the package root.
SystemDNSResolver ¶
DNS resolver using the system getaddrinfo implementation.
Resolves hostnames with :func:socket.getaddrinfo on a background thread so the lookup can be bounded by a timeout. It implements the :class:~httptap.interfaces.DNSResolver protocol and is the default resolver used by the analyzer.
方法:
-
resolve–Resolve host and return IP, family label, and elapsed milliseconds.
resolve ¶
Resolve host and return IP, family label, and elapsed milliseconds.
参数:
-
host(str) –Hostname to resolve (e.g., "example.com").
-
port(int) –Port number used to hint the address lookup.
-
timeout(float) –Maximum time to wait for resolution, in seconds.
返回:
-
str–Tuple of
(ip_address, ip_family, elapsed_ms)whereip_family -
str–is one of
"IPv4","IPv6", or"AF_<num>"for other -
float–address families, and
elapsed_msis the resolution time in -
tuple[str, str, float]–milliseconds.
引发:
-
DNSResolutionError–If resolution times out, the lookup fails, or no usable address record is returned.
源代码位于: httptap/implementations/dns.py
SocketTLSInspector ¶
TLS inspector that performs a dedicated TLS handshake using ssl.
Opens a short-lived TCP connection, performs a TLS handshake, and extracts the negotiated version, cipher suite, and leaf-certificate details into a :class:~httptap.models.NetworkInfo. Implements the :class:~httptap.interfaces.TLSInspector protocol and is the default inspector used by the analyzer.
参数:
-
verify(bool, 默认:True) –Whether to verify TLS certificates.
-
ca_bundle_path(str | None, 默认:None) –Path to custom CA certificate bundle (PEM format). Only used when verify is True. If None, uses system CA bundle.
方法:
-
inspect–Inspect TLS connection and extract metadata.
源代码位于: httptap/implementations/tls.py
inspect ¶
inspect(
host: str, port: int, timeout: float
) -> NetworkInfo
Inspect TLS connection and extract metadata.
参数:
-
host(str) –Hostname to connect to, also used for SNI.
-
port(int) –Port number (typically 443 for HTTPS).
-
timeout(float) –Connection timeout in seconds. The probe is additionally capped by
TLS_PROBE_MAX_TIMEOUT_SECONDS.
返回:
-
NetworkInfo–A NetworkInfo populated with the resolved IP, negotiated TLS
-
NetworkInfo–version and cipher, and leaf-certificate details when available.
引发:
-
TLSInspectionError–If the connection or TLS handshake fails.
源代码位于: httptap/implementations/tls.py
PerfCounterTimingCollector ¶
High-precision timing collector using time.perf_counter().
Records monotonic timestamps as each request phase is marked and derives DNS, TTFB, and total durations from them. Implements the :class:~httptap.interfaces.TimingCollector protocol and is the default collector used by the analyzer. A fresh instance is created per request.
方法:
-
mark_dns_start–Record the beginning of DNS resolution.
-
mark_dns_end–Record the completion of DNS resolution.
-
mark_request_start–Record the moment the HTTP request starts.
-
mark_ttfb–Record when the first response byte is received.
-
mark_request_end–Record when the response body transfer completes.
-
get_metrics–Build a TimingMetrics instance populated with collected timings.
源代码位于: httptap/implementations/timing.py
mark_dns_start ¶
mark_dns_end ¶
mark_request_start ¶
mark_ttfb ¶
mark_request_end ¶
get_metrics ¶
get_metrics() -> TimingMetrics
Build a TimingMetrics instance populated with collected timings.
返回:
-
TimingMetrics–A TimingMetrics with
dns_ms,ttfb_ms, andtotal_ms -
TimingMetrics–computed from the recorded marks. Call
calculate_derived()on -
TimingMetrics–the result to populate
wait_msandxfer_ms.
源代码位于: httptap/implementations/timing.py
WaterfallVisualizer ¶
Bases: Visualizer
Creates waterfall diagrams showing request phase timelines.
Renders each request phase (DNS, connect, TLS, wait, transfer) as a horizontally offset bar in the terminal using Rich, so the relative cost of each phase is visible at a glance. Implements the :class:~httptap.interfaces.Visualizer protocol.
属性:
-
console–Rich console used for output.
-
max_bar_width–Maximum width, in characters, of the timeline bars.
参数:
-
console(Console) –Rich console instance used to print the timeline.
-
max_bar_width(int, 默认:80) –Maximum width, in characters, of the timeline bars.
方法:
-
render–Render a waterfall timeline for the provided step if data is valid.
源代码位于: httptap/visualizer.py
render ¶
render(step: StepMetrics) -> None
Render a waterfall timeline for the provided step if data is valid.
Steps that errored or have a non-positive total time are skipped and produce no output.
参数:
-
step(StepMetrics) –Step metrics containing timing, network, and response data.
源代码位于: httptap/visualizer.py
JSONExporter ¶
Bases: Exporter
Exports HTTP analysis data to JSON format.
Handles serialization of step metrics and summary information to structured JSON files.
属性:
-
console–Rich console for user feedback.
参数:
-
console(Console) –Rich console instance.
方法:
-
export–Export analysis data to JSON file.
源代码位于: httptap/exporter.py
export ¶
export(
steps: Sequence[StepMetrics],
initial_url: str,
output_path: str,
*,
slo_result: SLOResult | None = None,
) -> None
Export analysis data to JSON file.
Creates a structured JSON file with all step metrics, timing information, and summary data.
参数:
-
steps(Sequence[StepMetrics]) –Sequence of step metrics to export.
-
initial_url(str) –Initial URL that was analyzed.
-
output_path(str) –Path to output JSON file.
-
slo_result(SLOResult | None, 默认:None) –Optional SLO evaluation result to embed under
summary.slo.
引发:
-
IOError–If file cannot be written.
源代码位于: httptap/exporter.py
HTTPClientRequestExecutor ¶
RequestExecutor that delegates to the built-in HTTP client.
This is the default executor used by :class:~httptap.analyzer.HTTPTapAnalyzer. It forwards each request to :func:httptap.http_client.make_request, which instruments DNS, connection, TLS, and transfer timing.
方法:
-
execute–Perform an HTTP request using the default client.
execute ¶
execute(options: RequestOptions) -> RequestOutcome
Perform an HTTP request using the default client.
参数:
-
options(RequestOptions) –Fully populated request parameters.
返回:
-
RequestOutcome–A RequestOutcome bundling the timing, network, and response data.
引发:
-
HTTPClientError–If the underlying HTTP request fails.
源代码位于: httptap/request_executor.py
SLO evaluation¶
The SLO helpers are exposed at the package root so programmatic callers can parse, evaluate, and serialize latency budgets exactly as the CLI does.
from httptap import HTTPTapAnalyzer, evaluate_slo, parse_slo_spec, select_step_for_evaluation
analyzer = HTTPTapAnalyzer(follow_redirects=True)
steps = analyzer.analyze_url("https://api.example.com/health")
thresholds = parse_slo_spec("total=500,ttfb=200")
target = select_step_for_evaluation(steps)
if target is not None:
result = evaluate_slo(target, thresholds)
if not result.passed:
for violation in result.violations:
print(f"{violation.key}: {violation.actual_ms:.1f}ms > {violation.threshold_ms:g}ms")
parse_slo_spec ¶
Parse an --slo specification string.
The expected grammar is a comma-separated list of KEY=MS pairs. Whitespace around keys and values is tolerated. Keys are case-insensitive and normalised to lowercase.
参数:
-
raw(str) –String passed via
--slo, e.g."total=500,ttfb=200".
返回:
-
dict[str, float]–Mapping of lowercase SLO key to threshold in milliseconds.
引发:
-
SLOSpecError–If the string is empty, a pair is malformed, a key is unknown, a key is duplicated, or a value is not a positive, finite number.
示例:
>>> parse_slo_spec("total=500,ttfb=200")
{'total': 500.0, 'ttfb': 200.0}
>>> parse_slo_spec("Total=500")
{'total': 500.0}
源代码位于: httptap/slo.py
evaluate_slo ¶
evaluate_slo(
step: StepMetrics, thresholds: Mapping[str, float]
) -> SLOResult
Evaluate timings on a single step against SLO thresholds.
参数:
-
step(StepMetrics) –Step whose
timingis compared to the thresholds. -
thresholds(Mapping[str, float]) –Mapping of SLO key to threshold in milliseconds. Every key must be a member of :data:
SLO_KEYS.
返回:
-
SLOResult–class:
SLOResultlisting any violations in ascending -
SLOResult–alphabetical order of the user-supplied threshold keys. The
-
SLOResult–order is stable so the JSON export is reproducible.
引发:
-
SLOSpecError–If
thresholdscontains a key that is not a member of :data:SLO_KEYS. Programmatic callers are expected to validate input via :func:parse_slo_specfirst; this check guards against accidental misuse.
源代码位于: httptap/slo.py
select_step_for_evaluation ¶
select_step_for_evaluation(
steps: Sequence[StepMetrics],
) -> StepMetrics | None
Pick the step whose timing should be checked against SLO.
By convention, SLOs apply to the final successful step of a redirect chain (the one that actually served the user's request). If every step errored out, returns None — the caller is expected to treat that as a network failure rather than an SLO violation.
参数:
-
steps(Sequence[StepMetrics]) –Steps returned by
HTTPTapAnalyzer.analyze_url.
返回:
-
StepMetrics | None–Final successful step, or
Noneif there is no such step.
源代码位于: httptap/slo.py
SLOResult dataclass ¶
SLOResult(
thresholds_ms: dict[str, float] = dict(),
violations: tuple[SLOViolation, ...] = (),
)
Result of evaluating timings against a set of SLO thresholds.
Produced by :func:evaluate_slo, which guarantees the contract used by the rest of the codebase:
thresholds_msis a freshdictsnapshot of the input mapping — safe to mutate by the caller without affecting the result object's serialization.violationsis atuplesorted alphabetically by :attr:SLOViolation.key, making :meth:to_dictoutput byte-stable across evaluations with the same input.
The dataclass is frozen=True so attribute reassignment is blocked; this is shallow immutability (as with any Python frozen dataclass) — external callers who hand-construct SLOResult with mutable containers should not mutate them after handover.
:class:SLOResult is not hashable (thresholds_ms is a dict) and therefore cannot be used as a dict key or added to a set; equality comparison via == works and is structural.
属性:
-
thresholds_ms(dict[str, float]) –User-supplied budgets keyed by SLO key.
-
violations(tuple[SLOViolation, ...]) –Violations sorted alphabetically by
key. When empty, the evaluation passed.
方法:
-
to_dict–Serialize to a plain
dictfor JSON export.
to_dict ¶
Serialize to a plain dict for JSON export.
Threshold keys are emitted in alphabetical order so that two evaluations with the same user input always produce byte-identical JSON (useful for diffing and cache keys).
返回:
-
dict[str, Any]–Mapping with keys
pass,thresholds_ms,violations.
源代码位于: httptap/slo.py
SLOViolation dataclass ¶
A single threshold violation.
属性:
-
key(str) –Timing phase key (e.g.,
"total","ttfb"). -
threshold_ms(float) –Budget supplied by the user, in milliseconds.
-
actual_ms(float) –Measured timing value, in milliseconds.
方法:
-
to_dict–Serialize to a plain
dictfor JSON export.
delta_ms property ¶
Overrun over the budget, in milliseconds.
By construction :func:evaluate_slo only emits violations where actual_ms > threshold_ms, so this value is always strictly positive for objects produced by this module. Callers that instantiate SLOViolation directly should preserve this invariant to keep downstream output consistent.
to_dict ¶
Serialize to a plain dict for JSON export.
返回:
-
dict[str, float | str]–Mapping with keys
key,threshold_ms,actual_ms, -
dict[str, float | str]–delta_ms.
源代码位于: httptap/slo.py
SLOSpecError ¶
Bases: ValueError
Raised when an --slo specification cannot be parsed.
SLO_KEYS module-attribute ¶
SLO_KEYS: frozenset[str] = frozenset(
{
"dns",
"connect",
"tls",
"ttfb",
"wait",
"xfer",
"total",
}
)
Error handling¶
httptap returns errors as part of StepMetrics rather than raising during analysis.
from httptap import HTTPTapAnalyzer
analyzer = HTTPTapAnalyzer()
steps = analyzer.analyze_url("https://invalid-domain.example")
step = steps[0]
if step.has_error:
print(f"Error: {step.error}")
else:
print(f"Status: {step.response.status}")
What's Next?¶
-
HTTPTapAnalyzer, data models, utilities
-
Extend with custom implementations
-
Real-world examples and patterns