1+ <p align =" center " >
2+ <img src =" docs/assets/httptap-banner.svg " alt =" httptap " width =" 100% " />
3+ </p >
4+
15# httptap
26
37<table >
2226 <a href="https://github.com/ozeranskii/httptap/actions/workflows/codeql.yml">
2327 <img src="https://github.com/ozeranskii/httptap/actions/workflows/codeql.yml/badge.svg" alt="CodeQL" />
2428 </a><br />
29+ <a href="https://scorecard.dev/viewer/?uri=github.com/ozeranskii/httptap">
30+ <img src="https://api.scorecard.dev/projects/github.com/ozeranskii/httptap/badge" alt="OpenSSF Scorecard" />
31+ </a><br />
2532 <a href="https://codecov.io/github/ozeranskii/httptap">
2633 <img src="https://codecov.io/github/ozeranskii/httptap/graph/badge.svg?token=OFOHOI1X5J" alt="Coverage" />
2734 </a><br />
@@ -50,6 +57,39 @@ performance baselines.
5057
5158---
5259
60+ ## Table of Contents
61+
62+ - [ Highlights] ( #highlights )
63+ - [ How it compares] ( #how-it-compares )
64+ - [ Requirements] ( #requirements )
65+ - [ Installation] ( #installation )
66+ - [ Using Homebrew (macOS/Linux)] ( #using-homebrew-macoslinux )
67+ - [ Using ` uv ` ] ( #using-uv )
68+ - [ Using ` pip ` ] ( #using-pip )
69+ - [ From source] ( #from-source )
70+ - [ Shell completions] ( #shell-completions )
71+ - [ Quick Start] ( #quick-start )
72+ - [ Basic GET Request] ( #basic-get-request )
73+ - [ POST Request with Data] ( #post-request-with-data )
74+ - [ Other HTTP Methods] ( #other-http-methods )
75+ - [ Custom Headers] ( #custom-headers )
76+ - [ Redirects and JSON Export] ( #redirects-and-json-export )
77+ - [ Output Modes] ( #output-modes )
78+ - [ Advanced Usage] ( #advanced-usage )
79+ - [ Environment Variables] ( #environment-variables )
80+ - [ Exit Codes] ( #exit-codes )
81+ - [ Releasing] ( #releasing )
82+ - [ Sample Output] ( #sample-output )
83+ - [ JSON Export Structure] ( #json-export-structure )
84+ - [ Metrics-only scripting] ( #metrics-only-scripting )
85+ - [ Advanced Usage] ( #advanced-usage-1 )
86+ - [ Development] ( #development )
87+ - [ Contributing] ( #contributing )
88+ - [ License] ( #license )
89+ - [ Acknowledgements] ( #acknowledgements )
90+
91+ ---
92+
5393## Highlights
5494
5595- ** Phase-by-phase timing** – precise measurements built from httpcore trace hooks (with sane fallbacks when metal-level
@@ -67,6 +107,33 @@ performance baselines.
67107
68108---
69109
110+ ## How it compares
111+
112+ | Feature | ` httptap ` | ` curl -w ` | [ ` httpstat ` ] ( https://github.com/reorx/httpstat ) | ` httpie ` |
113+ | ------------------------------------------| :---------:| :----------------------:| :-----------------------------------------------:| :-----------------:|
114+ | Phase-by-phase timing (DNS/TCP/TLS/TTFB) | ✅ | ✅ (format str) | ✅ | ❌ |
115+ | Rich waterfall visualization | ✅ | ❌ | ⚠️ text bars | ❌ |
116+ | Redirect chain with per-step timing | ✅ | ❌ | ❌ | ❌ |
117+ | JSON export (machine-readable) | ✅ | ✅ (` -w '%{json}' ` ) | ✅ (` --format json/jsonl ` , v1 schema) | ❌ (no metrics) |
118+ | Metrics-only mode for scripting | ✅ | ✅ | ✅ (` --format json ` ) | ❌ |
119+ | SLO threshold checking | ❌ | ❌ | ✅ (` --slo total=500,... ` ) | ❌ |
120+ | TLS certificate inspection (CN, expiry) | ✅ | ⚠️ via ` -v ` | ❌ | ❌ |
121+ | IPv4/IPv6 reporting | ✅ family | ⚠️ IP via ` remote_ip ` | ⚠️ IP only (` remote_ip ` /` remote_port ` ) | ❌ |
122+ | HTTP/2 support | ✅ | ✅ | ⚠️ via curl passthrough | ⚠️ plugin only |
123+ | Proxy with source attribution | ✅ | ⚠️ no attribution | ⚠️ via curl passthrough | ⚠️ no attribution |
124+ | Custom CA bundle | ✅ | ✅ | ⚠️ via curl passthrough | ✅ |
125+ | Extensible Python API | ✅ | ❌ (pycurl ≠ same API) | ❌ | ⚠️ via requests |
126+ | Curl-compatible flags | ✅ | — | ✅ (passes through) | ❌ |
127+ | Zero system dependencies | ✅ | ✅ | needs curl | ✅ |
128+
129+ ** When to pick what:**
130+ - ** ` httptap ` ** — interactive troubleshooting, regression analysis, and scripted baselines with structured JSON.
131+ - ** ` curl -w ` ** — one-off shell checks where curl is already the dependency.
132+ - ** ` httpstat ` ** — quick visual breakdown on top of an existing curl install.
133+ - ** ` httpie ` ** — general-purpose request/response exploration, not latency profiling.
134+
135+ ---
136+
70137## Requirements
71138
72139- Python 3.10-3.15 (CPython)
@@ -158,7 +225,7 @@ Once completions are installed, you can use `Tab` to autocomplete commands and o
158225``` shell
159226# Complete command options
160227httptap --< TAB>
161- # Shows: --follow, --timeout, --no-http2, --ignore-ssl, --cacert, --proxy, --header, --compact, --metrics-only, --json, --version, --help
228+ # Shows: --method, --data, -- follow, --timeout, --no-http2, --ignore-ssl, --cacert, --proxy, --header, --compact, --metrics-only, --json, --version, --help
162229
163230# Complete after typing partial option
164231httptap --fol< TAB>
@@ -306,6 +373,54 @@ can confirm what path was used (e.g., `(from arg --proxy)`,
306373
307374---
308375
376+ ## Environment Variables
377+
378+ httptap reads the following environment variables at runtime. All of them are
379+ overridable via CLI flags, and the actual source used for each request is
380+ recorded in the output and JSON export.
381+
382+ | Variable | Purpose | Overridden by |
383+ | ---------------------------------------| --------------------------------------------------------------------------------------------------------------| -----------------------|
384+ | ` HTTP_PROXY ` / ` http_proxy ` | Proxy URL used for ` http:// ` targets. | ` -x/--proxy ` |
385+ | ` HTTPS_PROXY ` / ` https_proxy ` | Proxy URL used for ` https:// ` targets. | ` -x/--proxy ` |
386+ | ` ALL_PROXY ` / ` all_proxy ` | Fallback proxy URL when scheme-specific variables are unset. | ` -x/--proxy ` |
387+ | ` NO_PROXY ` / ` no_proxy ` | Comma-separated exclusion list (supports ` * ` , leading ` . ` , exact matches). Bypassed entries connect direct. | ` --proxy "" ` |
388+ | ` NO_COLOR ` | Disables ANSI colors in all Rich output (honors the [ NO_COLOR] ( https://no-color.org ) convention). | — |
389+ | ` FORCE_COLOR ` | Forces colored output even when stdout is not a TTY (Rich convention). | — |
390+ | ` TERM=dumb ` | Rich downgrades to plain-text rendering. | — |
391+
392+ > Precedence for proxy configuration: explicit ` -x/--proxy ` → ` --proxy "" `
393+ > (disables env) → ` HTTPS_PROXY ` /` HTTP_PROXY ` /` ALL_PROXY ` (scheme-matching) →
394+ > ` NO_PROXY ` exclusion → direct connection.
395+
396+ ---
397+
398+ ## Exit Codes
399+
400+ httptap follows the BSD ` sysexits.h ` convention so it integrates cleanly with
401+ shell pipelines, CI jobs, and systemd services.
402+
403+ | Code | Symbol | Meaning |
404+ | :-----:| -------------------------| ------------------------------------------------------------|
405+ | ` 0 ` | ` EX_OK ` | Success. |
406+ | ` 64 ` | ` EX_USAGE ` | Invalid command-line arguments. |
407+ | ` 70 ` | ` EX_SOFTWARE ` | Internal error (unexpected exception, bug). |
408+ | ` 75 ` | ` EX_TEMPFAIL ` | Network / TLS error (partial output may still be rendered). |
409+ | ` 128 + N ` | Signal offset | Killed by signal ` N ` (e.g., ` 130 ` for ` SIGINT ` / Ctrl-C). |
410+
411+ Example — fail a CI job only on usage errors, tolerating transient network
412+ issues:
413+
414+ ``` shell
415+ httptap --metrics-only https://api.example.com/health
416+ rc=$?
417+ if [ " $rc " = 64 ] || [ " $rc " = 70 ]; then
418+ exit " $rc "
419+ fi
420+ ```
421+
422+ ---
423+
309424
310425## Releasing
311426
@@ -325,8 +440,9 @@ can confirm what path was used (e.g., `(from arg --proxy)`,
325440 - Commit changes and create a git tag
326441 - Run full test suite on the tagged version
327442 - Build wheel and source distribution
443+ - Generate SBOM in CycloneDX and SPDX formats via Syft
328444 - Publish to PyPI via Trusted Publishing (OIDC)
329- - Create GitHub Release with generated notes
445+ - Create GitHub Release with wheel, sdist, and SBOM assets
330446
331447---
332448
@@ -577,6 +693,6 @@ details.
577693
578694- Built on the shoulders of fantastic
579695 libraries: [ httpx] ( https://www.python-httpx.org/ ) , [ httpcore] ( https://github.com/encode/httpcore ) ,
580- and [ Rich] ( https://github.com/Textualize/rich ) .
696+ [ dnspython ] ( https://www.dnspython.org/ ) , and [ Rich] ( https://github.com/Textualize/rich ) .
581697- Inspired by the tooling ecosystem around web performance (e.g., DevTools waterfalls, ` curl --trace ` ).
582698- Special thanks to everyone who opens issues, shares ideas, or contributes patches.
0 commit comments