aboutsummaryrefslogtreecommitdiffstats
path: root/docs/src/content/addons-commands.md
blob: f689d763f23f7b33f84b051764e1e18353ebc85f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
---
title: "Commands"
menu:
    addons:
        weight: 4
---

# Commands

Commands allow users to actively interact with addons - querying their state,
commanding them to perform actions, and having them transform data. Like
[options]({{< relref addons-options >}}), commands are typed, and both
invocations and data returned from commands are checked at runtime. Commands are
a very powerful construct - for instance, all user interaction in mitmproxy
console are built by binding commands to keys.


## Simple example

Let's begin with a simple example.

{{< example src="examples/addons/commands-simple.py" lang="py" >}}

To see this example in action, start mitmproxy console with the addon loaded:

{{< highlight bash  >}}
> mitmproxy -s ./examples/addons/commands-simple.py
{{< /highlight >}}

Now, make sure the event log is showing, and then execute the command at the
prompt (started by typing ":"):

{{< highlight none>}}
:myaddon.inc
{{< /highlight >}}

Notice that tab completion works - our addon command has complete parity with
builtin commands. There are a few things to note about this example:

- Commands are declared through the `command.command` decorator. Each command
  has a unique name - by convention, we use period-separated names, with the
  name of the addon as a prefix.
- Annotating commands with types is mandatory, including the return type (in
  this case `None`). This allows mitmproxy to support addon commands throughout
  its toolset - runtime invocations are type checked, addon commands are
  included in the built-in help, the command editor in mitmproxy console can
  perform sophisticated completion and error checking, and so forth.


## Working with flows

Since command arguments are typed, we can provide special conveniences for
working with certain important data types. The most useful of these are the
`Flows` classes that represent mitmproxy traffic.

Consider the following addon:

{{< example src="examples/addons/commands-flows.py" lang="py" >}}

The `myaddon.addheader` command is quite simple: it takes a sequence of flows,
and adds a header to every request. The really interesting aspect of this
example is how users specify flows. Because mitmproxy can inspect the type
signature, it can expand a text flow selector into a sequence of flows for us
transparently. This means that the user has the full flexibility of [flow
filters]({{< relref addons-options >}}) available. Let's try it out.

Start by loading the addon into mitmproxy and sending some traffic through so we
have flows to work with:

{{< highlight bash  >}}
> mitmproxy -s ./examples/addons/commands-flows.py
{{< /highlight >}}

We can now invoke our toy command in various ways. Let's begin by running it
just on the currently focused flow:

{{< highlight none  >}}
:myaddon.addheader @focus
{{< /highlight >}}

We can also invoke it on all flows:

{{< highlight none  >}}
:myaddon.addheader @all
{{< /highlight >}}

Or only flows from **google.com**:

{{< highlight none  >}}
:myaddon.addheader ~d google.com
{{< /highlight >}}

What's more, we can trivially bind these commands to keyboard shortcuts within
mitmproxy if we plan to use them frequently. Flow selectors combined with
commands are amazingly powerful, and lets us build and expose re-usable functions
for operating on flows.


## Paths

Commands can take an arbitrary number of arguments. Let's build on the previous
example to illustrate this, and also demonstrate another special type: paths.

{{< example src="examples/addons/commands-paths.py" lang="py" >}}

Our command calculates a histogram of the domains in the specified set of flows,
and writes it to a path which is specified as the second argument to the
command. Try invoking it like this:

{{< highlight none  >}}
:myaddon.histogram @all /tmp/xxx
{{< /highlight >}}

Notice that mitmproxy provides tab completion both for the flow specification
and the path.



## Supported Types

The following types are supported for options. If you need to use a type not
listed here, please send us a pull request.

- Primitive types: `str`, `int`, `bool`
- Sequences: `typing.Sequence[str]`
- Flows and flow sequences: `flow.Flow` and `typing.Sequence[flow.Flow]`
- Multiple choice strings: `types.Choice`
- Meta-types: `types.Command` and `types.Arg`. These are for constructing
  commands that invoke other commands. This is most commonly useful in
  keybinding - see the built-in mitmproxy console keybindings for a rich suite
  of examples.
- Data types: `types.CutSpec` and `types.Data`. The cuts mechanism is in alpha
  at the moment, and provides a convenient way to snip up flow data.
- Path: `types.Path`