feat: add proxy template origin field and implement socket utilities for log streaming

This commit is contained in:
gabdevele
2026-05-07 10:54:57 +02:00 Unverified
parent 53dcdafdb1
commit 354ec150bc
32 changed files with 1681 additions and 1214 deletions
+40 -2
View File
@@ -9,7 +9,7 @@ from app.core.security import get_auth_context, require_authenticated_user
from app.models.health import HealthSnapshot
from app.models.proxy import ProxyCreateInput, ProxyDocument
from app.models.service import ServiceEndpointDocument
from app.services.mitmproxy.templates import BUILTIN_TEMPLATES
from app.services.mitmproxy.templates import list_file_templates
from app.services.mitmproxy.validator import ProxyCodeValidationError
proxy_router_module = importlib.import_module("app.api.proxy.router")
@@ -864,6 +864,8 @@ def test_stop_proxy_updates_runtime_state(client, monkeypatch: object):
def test_list_mitmproxy_templates_returns_builtins_and_custom(client, monkeypatch):
file_templates = list_file_templates()
async def fake_list_custom_templates():
return []
@@ -872,13 +874,19 @@ def test_list_mitmproxy_templates_returns_builtins_and_custom(client, monkeypatc
"list_custom_templates",
fake_list_custom_templates,
)
monkeypatch.setattr(
proxy_router_module,
"list_file_templates",
lambda: file_templates,
)
response = client.get("/proxy/mitmproxy/templates")
assert response.status_code == 200
body = response.json()
assert len(body) == len(BUILTIN_TEMPLATES)
assert len(body) == len(file_templates)
assert body[0]["built_in"] is True
assert body[0]["origin"] == "file"
assert body[0]["protocol"] in {"http", "tcp"}
assert isinstance(body[0]["tags"], list)
assert body[0]["action"] in {"block", "rewrite"}
@@ -906,6 +914,7 @@ def test_create_mitmproxy_template_validates_and_persists(client, monkeypatch):
"code": payload.code,
"source_url": payload.source_url,
"built_in": False,
"origin": "custom",
}
monkeypatch.setattr(
@@ -939,4 +948,33 @@ def test_create_mitmproxy_template_validates_and_persists(client, monkeypatch):
assert response.status_code == 201
assert response.json()["id"] == "custom-header"
assert response.json()["protocol"] == "http"
assert response.json()["origin"] == "custom"
assert captured["validated"] == "def response(flow):\n pass\n"
def test_create_mitmproxy_template_rejects_file_backed_id(client, monkeypatch):
monkeypatch.setattr(
proxy_router_module,
"file_template_ids",
lambda: {"http-block-path-traversal"},
)
response = client.post(
"/proxy/mitmproxy/templates",
json={
"id": "http-block-path-traversal",
"name": "Custom header",
"description": "Adds a custom response header",
"category": "http",
"protocol": "http",
"family": "custom",
"tags": [],
"action": "custom",
"summary": "Saved custom template.",
"behavior": "Applies the current script as-is.",
"code": "def response(flow):\n pass\n",
},
)
assert response.status_code == 409
assert "Template already exists" in response.json()["detail"]
+46 -3
View File
@@ -1,8 +1,12 @@
from app.services.mitmproxy.templates import BUILTIN_TEMPLATES
import logging
import yaml
from app.services.mitmproxy.templates import list_file_templates
def test_builtin_templates_use_four_space_indentation():
for template in BUILTIN_TEMPLATES:
def test_file_templates_use_four_space_indentation():
for template in list_file_templates():
for line in template.code.splitlines():
assert "\t" not in line, f"{template.id} contains a tab: {line!r}"
if not line.strip():
@@ -11,3 +15,42 @@ def test_builtin_templates_use_four_space_indentation():
assert indent % 4 == 0, (
f"{template.id} has non-4-space indentation: {line!r}"
)
def test_list_file_templates_loads_yaml_backed_templates():
templates = list_file_templates()
assert templates
assert all(template.origin == "file" for template in templates)
assert all(template.built_in is True for template in templates)
assert all(template.protocol in {"http", "tcp"} for template in templates)
def test_list_file_templates_skips_invalid_files(tmp_path, caplog):
path = tmp_path / "invalid.yaml"
path.write_text("[]\n", encoding="utf-8")
with caplog.at_level(logging.WARNING):
templates = list_file_templates(tmp_path)
assert templates == []
assert "Skipping template file" in caplog.text
def test_list_file_templates_skips_duplicate_ids(tmp_path, caplog):
payload = {
"id": "duplicate",
"name": "Duplicate",
"protocol": "http",
"description": "Duplicate template",
"code": "from mitmproxy import http\n",
}
document = yaml.safe_dump(payload, sort_keys=False)
(tmp_path / "one.yaml").write_text(document, encoding="utf-8")
(tmp_path / "two.yaml").write_text(document, encoding="utf-8")
with caplog.at_level(logging.WARNING):
templates = list_file_templates(tmp_path)
assert templates == []
assert "duplicate file-backed template id" in caplog.text