riciplay-miniproxy 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ dist/
2
+ __pycache__/
3
+ *.pyc
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zaidux
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,101 @@
1
+ Metadata-Version: 2.3
2
+ Name: riciplay-miniproxy
3
+ Version: 0.4.0
4
+ Summary: A lightweight HTTP/S interception proxy for security research — always-on capture, timing, scope guard, Repeater + Intruder dashboard
5
+ Project-URL: Homepage, https://github.com/Zaidux/miniproxy
6
+ Project-URL: Repository, https://github.com/Zaidux/miniproxy
7
+ Author: Zaidux
8
+ License: MIT
9
+ Keywords: bugbounty,interception,intruder,mitmproxy,proxy,repeater,security
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: MacOS
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Internet :: Proxy Servers
17
+ Classifier: Topic :: Security
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: flask>=3.0.0
20
+ Requires-Dist: mitmproxy>=10.0.0
21
+ Requires-Dist: requests>=2.31.0
22
+ Description-Content-Type: text/markdown
23
+
24
+ # MiniProxy
25
+
26
+ A lightweight HTTP/S interception proxy for security research — the standalone Burp-style toolkit from the [Riciplay](https://github.com/Zaidux/Riciplay) ecosystem. Built on **mitmproxy**, **Flask**, and **SQLite**.
27
+
28
+ Ships the **v4 capture engine** (the same addon the Riciplay CLI embeds):
29
+
30
+ - **Always-on capture** — every request/response is logged with full headers, bodies, and status codes. (The old intercept toggle silently produced empty captures on fresh DBs; it's gone.)
31
+ - **Static-asset streaming** — JS/CSS/images stream through without buffering, so heavy SPAs don't pay a per-flow decode tax.
32
+ - **Timing** — `ttfb_ms` / `total_ms` on every flow. Oracles and timing side-channels need numbers.
33
+ - **Scope guard** — `--scope '*.target.com'` keeps out-of-scope traffic out of your capture DB (or 403-blocks it with `--block-out-of-scope`).
34
+ - **Repeater** — pick a logged request, edit method/headers/body, resend, inspect.
35
+ - **Intruder** — mark parameters with `§param§` placeholders, supply a wordlist, fuzz every position; results highlighted by status code and stored in the DB.
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ # Python (PyPI)
41
+ pip install riciplay-miniproxy
42
+
43
+ # or Node (npm — installs the Python package on postinstall)
44
+ npm install -g riciplay-miniproxy
45
+ ```
46
+
47
+ Requires Python 3.10+ and [mitmproxy](https://mitmproxy.org/).
48
+
49
+ ## Quick start
50
+
51
+ ```bash
52
+ miniproxy start # proxy on :8080
53
+ miniproxy start --scope '*.target.com' # capture only in-scope traffic
54
+ miniproxy dashboard # web UI on :5000 (Log/Repeater/Intruder)
55
+ ```
56
+
57
+ Then point your browser/system at `http://127.0.0.1:8080` (HTTPS interception uses mitmproxy's CA — run `mitmdump` once and install `~/.mitmproxy/mitmproxy-ca-cert.pem` if you haven't).
58
+
59
+ ```bash
60
+ miniproxy log # recent captured requests (with timing; reads the DB directly)
61
+ miniproxy log --id 5 # full detail for request #5
62
+ miniproxy send --url https://example.com/api --method POST \
63
+ --headers '{"Content-Type":"application/json"}' \
64
+ --body '{"key":"value"}'
65
+ miniproxy status
66
+ miniproxy stop
67
+ ```
68
+
69
+ State (pid, port, default capture DB) lives under `~/.miniproxy/`.
70
+
71
+ ## The dashboard
72
+
73
+ `miniproxy dashboard` serves a dark-theme SPA:
74
+
75
+ - **Proxy** — capture status and scope
76
+ - **Log** — live request feed; click any row for full headers/bodies/timing
77
+ - **Repeater** — edit and resend any captured request
78
+ - **Intruder** — `§param§` placeholders + wordlist fuzzing, results by status code
79
+
80
+ ## Relation to the Riciplay CLI
81
+
82
+ The Riciplay CLI (`pip install riciplay-cli`) embeds this same engine with agent-first extras: per-session capture DBs, RULES.md-derived scope enforcement, headless replay with response diffing, and bounded payload sweeps driven by the AI agent. Use MiniProxy standalone when you want the manual Burp-like workflow; use Riciplay when you want the agent to drive.
83
+
84
+ ## Project structure
85
+
86
+ ```
87
+ src/miniproxy/
88
+ ├── addon/
89
+ │ ├── proxy.py # mitmproxy addon — v4 capture engine
90
+ │ └── db.py # SQLite handler (timing columns, intruder results, pruning)
91
+ ├── app.py # Flask dashboard (API + UI)
92
+ ├── intruder.py # §placeholder§ fuzzing engine
93
+ ├── server.py # start/stop/status process manager
94
+ └── __main__.py # the `miniproxy` entry point (start/stop/status/
95
+ # dashboard/send/log — log and send work without
96
+ # any dashboard running)
97
+ ```
98
+
99
+ ## License
100
+
101
+ MIT
@@ -0,0 +1,78 @@
1
+ # MiniProxy
2
+
3
+ A lightweight HTTP/S interception proxy for security research — the standalone Burp-style toolkit from the [Riciplay](https://github.com/Zaidux/Riciplay) ecosystem. Built on **mitmproxy**, **Flask**, and **SQLite**.
4
+
5
+ Ships the **v4 capture engine** (the same addon the Riciplay CLI embeds):
6
+
7
+ - **Always-on capture** — every request/response is logged with full headers, bodies, and status codes. (The old intercept toggle silently produced empty captures on fresh DBs; it's gone.)
8
+ - **Static-asset streaming** — JS/CSS/images stream through without buffering, so heavy SPAs don't pay a per-flow decode tax.
9
+ - **Timing** — `ttfb_ms` / `total_ms` on every flow. Oracles and timing side-channels need numbers.
10
+ - **Scope guard** — `--scope '*.target.com'` keeps out-of-scope traffic out of your capture DB (or 403-blocks it with `--block-out-of-scope`).
11
+ - **Repeater** — pick a logged request, edit method/headers/body, resend, inspect.
12
+ - **Intruder** — mark parameters with `§param§` placeholders, supply a wordlist, fuzz every position; results highlighted by status code and stored in the DB.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ # Python (PyPI)
18
+ pip install riciplay-miniproxy
19
+
20
+ # or Node (npm — installs the Python package on postinstall)
21
+ npm install -g riciplay-miniproxy
22
+ ```
23
+
24
+ Requires Python 3.10+ and [mitmproxy](https://mitmproxy.org/).
25
+
26
+ ## Quick start
27
+
28
+ ```bash
29
+ miniproxy start # proxy on :8080
30
+ miniproxy start --scope '*.target.com' # capture only in-scope traffic
31
+ miniproxy dashboard # web UI on :5000 (Log/Repeater/Intruder)
32
+ ```
33
+
34
+ Then point your browser/system at `http://127.0.0.1:8080` (HTTPS interception uses mitmproxy's CA — run `mitmdump` once and install `~/.mitmproxy/mitmproxy-ca-cert.pem` if you haven't).
35
+
36
+ ```bash
37
+ miniproxy log # recent captured requests (with timing; reads the DB directly)
38
+ miniproxy log --id 5 # full detail for request #5
39
+ miniproxy send --url https://example.com/api --method POST \
40
+ --headers '{"Content-Type":"application/json"}' \
41
+ --body '{"key":"value"}'
42
+ miniproxy status
43
+ miniproxy stop
44
+ ```
45
+
46
+ State (pid, port, default capture DB) lives under `~/.miniproxy/`.
47
+
48
+ ## The dashboard
49
+
50
+ `miniproxy dashboard` serves a dark-theme SPA:
51
+
52
+ - **Proxy** — capture status and scope
53
+ - **Log** — live request feed; click any row for full headers/bodies/timing
54
+ - **Repeater** — edit and resend any captured request
55
+ - **Intruder** — `§param§` placeholders + wordlist fuzzing, results by status code
56
+
57
+ ## Relation to the Riciplay CLI
58
+
59
+ The Riciplay CLI (`pip install riciplay-cli`) embeds this same engine with agent-first extras: per-session capture DBs, RULES.md-derived scope enforcement, headless replay with response diffing, and bounded payload sweeps driven by the AI agent. Use MiniProxy standalone when you want the manual Burp-like workflow; use Riciplay when you want the agent to drive.
60
+
61
+ ## Project structure
62
+
63
+ ```
64
+ src/miniproxy/
65
+ ├── addon/
66
+ │ ├── proxy.py # mitmproxy addon — v4 capture engine
67
+ │ └── db.py # SQLite handler (timing columns, intruder results, pruning)
68
+ ├── app.py # Flask dashboard (API + UI)
69
+ ├── intruder.py # §placeholder§ fuzzing engine
70
+ ├── server.py # start/stop/status process manager
71
+ └── __main__.py # the `miniproxy` entry point (start/stop/status/
72
+ # dashboard/send/log — log and send work without
73
+ # any dashboard running)
74
+ ```
75
+
76
+ ## License
77
+
78
+ MIT
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ // MiniProxy launcher — delegates to the Python package (riciplay-miniproxy).
3
+ //
4
+ // miniproxy <args> → python3 -m miniproxy <args>
5
+ //
6
+ // The Python package is installed by scripts/postinstall.js (pip install
7
+ // riciplay-miniproxy). If python3 is missing the user gets a clear error
8
+ // rather than a silent failure.
9
+
10
+ const { spawn } = require('child_process');
11
+
12
+ const args = process.argv.slice(2);
13
+ const proc = spawn('python3', ['-m', 'miniproxy', ...args], { stdio: 'inherit' });
14
+
15
+ proc.on('error', (err) => {
16
+ if (err.code === 'ENOENT') {
17
+ console.error('Error: python3 not found. MiniProxy is a Python tool — install Python 3.10+ first.');
18
+ process.exit(1);
19
+ }
20
+ console.error('Error:', err.message);
21
+ process.exit(1);
22
+ });
23
+
24
+ proc.on('close', (code) => process.exit(code ?? 1));
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "riciplay-miniproxy",
3
+ "version": "0.4.0",
4
+ "description": "A lightweight HTTP/S interception proxy for security research — always-on capture, timing, scope guard, Repeater + Intruder dashboard",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "miniproxy": "./bin/miniproxy"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1",
11
+ "prepublishOnly": "echo \"Ensure the Python package riciplay-miniproxy is published to PyPI first\"",
12
+ "postinstall": "node scripts/postinstall.js"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/Zaidux/miniproxy.git"
17
+ },
18
+ "keywords": [
19
+ "proxy",
20
+ "mitmproxy",
21
+ "interception",
22
+ "security",
23
+ "bugbounty",
24
+ "repeater",
25
+ "intruder",
26
+ "pentesting"
27
+ ],
28
+ "author": "Zaidux <zaiduabubakar777@gmail.com>",
29
+ "license": "MIT",
30
+ "bugs": {
31
+ "url": "https://github.com/Zaidux/miniproxy/issues"
32
+ },
33
+ "homepage": "https://github.com/Zaidux/miniproxy#readme",
34
+ "engines": {
35
+ "node": ">=14.0.0"
36
+ },
37
+ "os": [
38
+ "darwin",
39
+ "linux"
40
+ ],
41
+ "files": [
42
+ "bin/",
43
+ "scripts/postinstall.js",
44
+ "README.md",
45
+ "LICENSE"
46
+ ],
47
+ "dependencies": {},
48
+ "peerDependencies": {}
49
+ }
@@ -0,0 +1,50 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "riciplay-miniproxy"
7
+ version = "0.4.0"
8
+ description = "A lightweight HTTP/S interception proxy for security research — always-on capture, timing, scope guard, Repeater + Intruder dashboard"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ {name = "Zaidux"},
14
+ ]
15
+ keywords = ["proxy", "mitmproxy", "interception", "security", "bugbounty", "repeater", "intruder"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: POSIX :: Linux",
21
+ "Operating System :: MacOS",
22
+ "Programming Language :: Python :: 3",
23
+ "Topic :: Security",
24
+ "Topic :: Internet :: Proxy Servers",
25
+ ]
26
+ dependencies = [
27
+ "mitmproxy>=10.0.0",
28
+ "Flask>=3.0.0",
29
+ "requests>=2.31.0",
30
+ ]
31
+
32
+ [project.scripts]
33
+ miniproxy = "miniproxy.__main__:main"
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/Zaidux/miniproxy"
37
+ Repository = "https://github.com/Zaidux/miniproxy"
38
+
39
+ [tool.hatch.build.targets.wheel]
40
+ packages = ["src/miniproxy"]
41
+
42
+ [tool.hatch.build.targets.sdist]
43
+ include = [
44
+ "src/miniproxy",
45
+ "README.md",
46
+ "LICENSE",
47
+ "package.json",
48
+ "bin",
49
+ "scripts",
50
+ ]
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ // MiniProxy npm postinstall — installs the Python package from PyPI.
3
+ //
4
+ // This npm package is a thin launcher; the real implementation is the
5
+ // Python package `riciplay-miniproxy`. If it is not importable, pip
6
+ // install it. Failures are warnings, not errors: the user may be
7
+ // installing without network access or managing Python themselves.
8
+
9
+ const { execSync, spawnSync } = require('child_process');
10
+ const os = require('os');
11
+
12
+ console.log('\n🔌 Installing MiniProxy (HTTP/S interception proxy)...\n');
13
+
14
+ const isWin = os.platform() === 'win32';
15
+ const python = isWin ? 'python' : 'python3';
16
+ const pip = isWin ? 'pip' : 'pip3';
17
+
18
+ function hasCommand(cmd) {
19
+ try {
20
+ execSync(`${cmd} --version`, { stdio: 'ignore' });
21
+ return true;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ try {
28
+ const probe = spawnSync(python, ['-c', 'import miniproxy'], { stdio: 'ignore' });
29
+ if (probe.status === 0) {
30
+ console.log('✓ Python package `miniproxy` already importable.');
31
+ } else {
32
+ console.log('Installing riciplay-miniproxy from PyPI...');
33
+ execSync(`${pip} install --upgrade riciplay-miniproxy`, { stdio: 'inherit' });
34
+ console.log('✓ Installed riciplay-miniproxy.');
35
+ }
36
+ } catch (err) {
37
+ console.warn(
38
+ `\n⚠ Could not install the Python package automatically (${err.message}).\n` +
39
+ ' MiniProxy needs Python 3.10+ and mitmproxy. Install manually with:\n' +
40
+ ' pip install riciplay-miniproxy\n'
41
+ );
42
+ }
43
+
44
+ console.log('\nUsage: miniproxy start --port 8080 # then miniproxy dashboard\n');
@@ -0,0 +1,9 @@
1
+ """MiniProxy — a lightweight HTTP/S interception proxy for security research.
2
+
3
+ Ships the canonical v4 capture engine (the same addon the Riciplay CLI
4
+ embeds): always-on capture, static-asset streaming, per-flow TTFB/total
5
+ timing, and a RULES-style scope guard with skip/block modes — plus a Flask
6
+ dashboard (Log / Repeater / Intruder) and a small manager CLI.
7
+ """
8
+
9
+ __version__ = "0.4.0"
@@ -0,0 +1,150 @@
1
+ """MiniProxy entry point — ``miniproxy`` / ``python -m miniproxy``.
2
+
3
+ Subcommands:
4
+ start Start the interception proxy (mitmdump + v4 addon)
5
+ stop Stop the proxy
6
+ status Proxy status
7
+ dashboard Run the Flask dashboard (Log / Repeater / Intruder UI)
8
+ send Send a request through the dashboard's Repeater
9
+ log Show captured requests
10
+ """
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ import os
15
+ import sys
16
+
17
+
18
+ def main(argv: list[str] | None = None) -> int:
19
+ parser = argparse.ArgumentParser(
20
+ prog="miniproxy",
21
+ description="HTTP/S interception proxy for security research.",
22
+ )
23
+ sub = parser.add_subparsers(dest="command")
24
+
25
+ p_start = sub.add_parser("start", help="Start the interception proxy")
26
+ p_start.add_argument("--port", type=int, default=8080)
27
+ p_start.add_argument("--db", default=None, help="SQLite capture DB path")
28
+ p_start.add_argument("--scope", nargs="*", default=None,
29
+ help="Capture-scope hosts (*.domain wildcards); "
30
+ "out-of-scope traffic is not captured")
31
+ p_start.add_argument("--block-out-of-scope", action="store_true",
32
+ help="403-block out-of-scope traffic instead of passing it through")
33
+ p_start.add_argument("--mitmdump", default="mitmdump")
34
+
35
+ sub.add_parser("stop", help="Stop the proxy")
36
+ sub.add_parser("status", help="Proxy status")
37
+
38
+ p_dash = sub.add_parser("dashboard", help="Run the Flask dashboard")
39
+ p_dash.add_argument("--port", type=int, default=5000)
40
+ p_dash.add_argument("--host", default="127.0.0.1")
41
+
42
+ p_send = sub.add_parser("send", help="Send a request via the dashboard Repeater")
43
+ p_send.add_argument("--url", required=True)
44
+ p_send.add_argument("--method", default="GET")
45
+ p_send.add_argument("--headers", default="{}", help="JSON object of headers")
46
+ p_send.add_argument("--body", default="")
47
+
48
+ p_log = sub.add_parser("log", help="Show captured requests")
49
+ p_log.add_argument("--id", type=int, default=None)
50
+ p_log.add_argument("--limit", type=int, default=30)
51
+
52
+ args = parser.parse_args(argv)
53
+
54
+ if args.command == "start":
55
+ from miniproxy import server
56
+ result = server.start(
57
+ port=args.port, db_path=args.db, scope_hosts=args.scope,
58
+ out_of_scope="block" if args.block_out_of_scope else "skip",
59
+ mitmdump_path=args.mitmdump,
60
+ )
61
+ print(result["message"])
62
+ return 0 if result["status"] in ("started", "already_running") else 1
63
+
64
+ if args.command == "stop":
65
+ from miniproxy import server
66
+ result = server.stop()
67
+ print(result["message"])
68
+ return 0 if result["status"] in ("stopped", "not_running") else 1
69
+
70
+ if args.command == "status":
71
+ from miniproxy import server
72
+ result = server.status()
73
+ print(result["message"])
74
+ return 0 if result["status"] == "running" else 1
75
+
76
+ if args.command == "dashboard":
77
+ from miniproxy.app import app
78
+ app.run(host=args.host, port=args.port, debug=False)
79
+ return 0
80
+
81
+ if args.command == "send":
82
+ # Direct request — no dashboard needed (mirrors the Repeater API's
83
+ # semantics: no redirects, self-signed certs allowed, 15s timeout).
84
+ import json as _json
85
+
86
+ import requests
87
+ import urllib3
88
+
89
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
90
+ try:
91
+ headers = _json.loads(args.headers)
92
+ if not isinstance(headers, dict):
93
+ headers = {}
94
+ except ValueError:
95
+ print("Error: --headers must be a JSON object", file=sys.stderr)
96
+ return 1
97
+ try:
98
+ resp = requests.request(
99
+ method=args.method.upper(), url=args.url, headers=headers,
100
+ data=args.body, timeout=15, verify=False, allow_redirects=False,
101
+ )
102
+ except requests.RequestException as exc:
103
+ print(f"Error: {exc}", file=sys.stderr)
104
+ return 1
105
+ print(f"Status: {resp.status_code}")
106
+ print(f"Headers: {_json.dumps(dict(resp.headers), indent=2)}")
107
+ body_text = resp.text or ""
108
+ print(f"Body ({len(body_text)} chars):")
109
+ print(body_text[:2000] + ("..." if len(body_text) > 2000 else ""))
110
+ return 0
111
+
112
+ if args.command == "log":
113
+ # Reads the capture DB directly — the dashboard does not need to
114
+ # be running to inspect what the proxy captured.
115
+ from miniproxy.addon.db import Database
116
+ from miniproxy.server import STATE_DIR
117
+
118
+ db = Database(os.environ.get("MINIPROXY_DB_PATH") or (STATE_DIR / "proxy.db"))
119
+ if args.id is not None:
120
+ row = db.get_request(args.id)
121
+ if row is None:
122
+ print(f"No captured request with id={args.id}.", file=sys.stderr)
123
+ return 1
124
+ print(f"ID: {row.get('id')}")
125
+ print(f"Method: {row.get('method')}")
126
+ print(f"URL: {row.get('url')}")
127
+ print(f"Status: {row.get('response_code')}")
128
+ print(f"TTFB: {row.get('ttfb_ms')} ms | Total: {row.get('total_ms')} ms")
129
+ print(f"Headers: {str(row.get('headers') or '')[:500]}")
130
+ print(f"Body: {str(row.get('body') or '')[:1000]}")
131
+ return 0
132
+ logs = db.get_logs(limit=max(args.limit, 1))
133
+ print(f"{'ID':>4} {'METHOD':<7} {'STATUS':<5} {'MS':>7} URL")
134
+ print("-" * 72)
135
+ for r in logs:
136
+ ms = r.get("total_ms")
137
+ ms_s = f"{ms:.0f}" if isinstance(ms, (int, float)) else "?"
138
+ print(f"{r.get('id', '?'):>4} {r.get('method', '?'):<7} "
139
+ f"{r.get('response_code', '?'):<5} {ms_s:>7} "
140
+ f"{str(r.get('url', ''))[:60]}")
141
+ if not logs:
142
+ print("(no captured requests yet)")
143
+ return 0
144
+
145
+ parser.print_help()
146
+ return 1
147
+
148
+
149
+ if __name__ == "__main__":
150
+ sys.exit(main())
@@ -0,0 +1,7 @@
1
+ """MiniProxy addon package — the canonical v4 mitmproxy addon.
2
+
3
+ ``proxy.py`` and ``db.py`` are loaded by mitmdump BY PATH (``mitmdump -s
4
+ .../addon/proxy.py``); the ``__init__.py`` exists so the same files are
5
+ importable as a regular package (tests, tooling) via the try/except import
6
+ at the top of ``proxy.py``.
7
+ """