指令
指令
命令允许用户与插件进行积极的交互-查询其状态,命令他们执行操作以及让他们转换数据。像options
一样 ,将键入命令,并在运行时检查命令的调用和返回的数据。命令是一个非常强大的结构-例如,mitmproxy
控制台中的所有用户交互都是通过将命令绑定到键来构建的。
简单的例子
让我们从一个简单的例子开始。
"""Add a custom command to mitmproxy's command prompt."""
from mitmproxy import command
from mitmproxy import ctx
class MyAddon:
def __init__(self):
self.num = 0
@command.command("myaddon.inc")
def inc(self) -> None:
self.num += 1
ctx.log.info(f"num = {self.num}")
addons = [
MyAddon()
]
要查看实际的示例,请在加载了加载项的情况下启动mitmproxy控制台:
> mitmproxy -s ./examples/addons/commands-simple.py
现在,确保显示事件日志,然后在提示符下执行命令(从键入“:”开始):
:myaddon.inc
请注意,制表符补全有效-我们的addon命令与内置命令完全相同。关于此示例,需要注意以下几点:
- 命令通过
command.command
装饰器声明。每个命令都有一个唯一的名称-按照惯例,我们使用句点分隔的名称,并以插件的名称作为前缀。 - 必须使用类型注释命令,包括返回类型(在这种情况下为
None
)。这使mitmproxy可以在其整个工具集中支持附加命令-运行时调用经过类型检查,附加命令包含在内置帮助中,mitmproxy控制台中的命令编辑器可以执行复杂的完成和错误检查,等等。
处理流程
由于键入了命令参数,因此我们可以为使用某些重要数据类型提供特殊的便利。其中最有用的是Flows
代表mitmproxy
流量的 类。
考虑以下插件:
"""Handle flows as command arguments."""
import typing
from mitmproxy import command
from mitmproxy import ctx
from mitmproxy import flow
class MyAddon:
@command.command("myaddon.addheader")
def addheader(self, flows: typing.Sequence[flow.Flow]) -> None:
for f in flows:
f.request.headers["myheader"] = "value"
ctx.log.alert("done")
addons = [
MyAddon()
]
该myaddon.addheader命令非常简单:它需要一系列流程,并向每个请求添加标头。这个示例真正有趣的方面是用户如何指定流。由于mitmproxy可以检查类型签名,因此可以透明地将文本流选择器扩展为一系列流。这意味着用户可以充分利用流量过滤器的灵活性。让我们尝试一下。
首先将加载项加载到mitmproxy中并通过发送一些流量,以便我们可以使用以下流程:
> mitmproxy -s ./examples/addons/commands-flows.py
现在,我们可以通过多种方式调用我们的玩具命令。让我们从仅在当前集中的流程上运行它开始:
:myaddon.addheader @focus
我们还可以在所有流上调用它:
:myaddon.addheader @all
或仅来自google.com:
:myaddon.addheader ~d google.com
此外,如果计划频繁使用这些命令,则可以将这些命令简单地绑定到mitmproxy内的键盘快捷键上。流选择器与命令相结合,功能强大,可让我们构建和公开可重用的函数,以对流进行操作。
路径
命令可以带有任意数量的参数。让我们以前面的示例为基础进行说明,并演示另一种特殊类型:路径。
"""Handle file paths as command arguments."""
import typing
from mitmproxy import command
from mitmproxy import ctx
from mitmproxy import flow
from mitmproxy import types
class MyAddon:
@command.command("myaddon.histogram")
def histogram(
self,
flows: typing.Sequence[flow.Flow],
path: types.Path,
) -> None:
totals = {}
for f in flows:
totals[f.request.host] = totals.setdefault(f.request.host, 0) + 1
with open(path, "w+") as fp:
for cnt, dom in sorted([(v, k) for (k, v) in totals.items()]):
fp.write("%s: %s\n" % (cnt, dom))
ctx.log.alert("done")
addons = [
MyAddon()
]
我们的命令计算指定流集合中域的直方图,并将其写入指定为命令第二个参数的路径。尝试像这样调用它:
:myaddon.histogram @all /tmp/xxx
请注意,mitmproxy为流规范和路径提供了制表符补全。
支持的类型
选项支持以下类型。如果您需要使用此处未列出的类型,请向我们发送拉取请求。
- 基本类型:
str,int,bool
- 顺序:
typing.Sequence[str]
- 流和流序列:
flow.Flow
和typing.Sequence[flow.Flow]
- 多选字符串:
types.Choice
- 元类型:
types.Command
和types.Arg
。这些用于构造调用其他命令的命令。这在键绑定中最通常有用-请参阅内置的mitmproxy控制台键绑定,以获取大量示例。 - 数据类型:
types.CutSpec和types.Data
。目前,cuts机制处于alpha状态,并提供了一种便捷的方式来截取流数据。 - 小路:
types.Path