2025-12-25 upload
This commit is contained in:
83
venv/Lib/site-packages/mitmproxy/addons/modifybody.py
Normal file
83
venv/Lib/site-packages/mitmproxy/addons/modifybody.py
Normal file
@@ -0,0 +1,83 @@
|
||||
import logging
|
||||
import re
|
||||
from collections.abc import Sequence
|
||||
|
||||
from mitmproxy import ctx
|
||||
from mitmproxy import exceptions
|
||||
from mitmproxy.addons.modifyheaders import ModifySpec
|
||||
from mitmproxy.addons.modifyheaders import parse_modify_spec
|
||||
from mitmproxy.log import ALERT
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ModifyBody:
|
||||
def __init__(self) -> None:
|
||||
self.replacements: list[ModifySpec] = []
|
||||
|
||||
def load(self, loader):
|
||||
loader.add_option(
|
||||
"modify_body",
|
||||
Sequence[str],
|
||||
[],
|
||||
"""
|
||||
Replacement pattern of the form "[/flow-filter]/regex/[@]replacement", where
|
||||
the separator can be any character. The @ allows to provide a file path that
|
||||
is used to read the replacement string.
|
||||
""",
|
||||
)
|
||||
|
||||
def configure(self, updated):
|
||||
if "modify_body" in updated:
|
||||
self.replacements = []
|
||||
for option in ctx.options.modify_body:
|
||||
try:
|
||||
spec = parse_modify_spec(option, True)
|
||||
except ValueError as e:
|
||||
raise exceptions.OptionsError(
|
||||
f"Cannot parse modify_body option {option}: {e}"
|
||||
) from e
|
||||
|
||||
self.replacements.append(spec)
|
||||
|
||||
stream_and_modify_conflict = (
|
||||
ctx.options.modify_body
|
||||
and ctx.options.stream_large_bodies
|
||||
and ("modify_body" in updated or "stream_large_bodies" in updated)
|
||||
)
|
||||
if stream_and_modify_conflict:
|
||||
logger.log(
|
||||
ALERT,
|
||||
"Both modify_body and stream_large_bodies are active. "
|
||||
"Streamed bodies will not be modified.",
|
||||
)
|
||||
|
||||
def request(self, flow):
|
||||
if flow.response or flow.error or not flow.live:
|
||||
return
|
||||
self.run(flow)
|
||||
|
||||
def response(self, flow):
|
||||
if flow.error or not flow.live:
|
||||
return
|
||||
self.run(flow)
|
||||
|
||||
def run(self, flow):
|
||||
for spec in self.replacements:
|
||||
if spec.matches(flow):
|
||||
try:
|
||||
replacement = spec.read_replacement()
|
||||
except OSError as e:
|
||||
logging.warning(f"Could not read replacement file: {e}")
|
||||
continue
|
||||
if flow.response:
|
||||
flow.response.content = re.sub(
|
||||
spec.subject,
|
||||
replacement,
|
||||
flow.response.content,
|
||||
flags=re.DOTALL,
|
||||
)
|
||||
else:
|
||||
flow.request.content = re.sub(
|
||||
spec.subject, replacement, flow.request.content, flags=re.DOTALL
|
||||
)
|
||||
Reference in New Issue
Block a user