diff options
author | Thomas Kriechbaumer <thomas@kriechbaumer.name> | 2020-04-04 15:31:38 +0200 |
---|---|---|
committer | Thomas Kriechbaumer <thomas@kriechbaumer.name> | 2020-04-04 15:36:13 +0200 |
commit | 678be7a052007e26939b5f0cfa13200ab032cf86 (patch) | |
tree | 6c571ae26edff40621b85c1330d1f89d96094f10 | |
parent | 6acabbb4f5977427dd08adb0d32b06c0007315d2 (diff) | |
download | mitmproxy-678be7a052007e26939b5f0cfa13200ab032cf86.tar.gz mitmproxy-678be7a052007e26939b5f0cfa13200ab032cf86.tar.bz2 mitmproxy-678be7a052007e26939b5f0cfa13200ab032cf86.zip |
improve scripting docs
-rw-r--r-- | docs/src/content/addons-events.md | 16 | ||||
-rw-r--r-- | docs/src/content/addons-scripting.md | 33 | ||||
-rw-r--r-- | docs/src/content/concepts-commands.md | 10 | ||||
-rw-r--r-- | docs/src/themes/mitmproxydocs/layouts/partials/header.html | 2 | ||||
-rw-r--r-- | examples/addons/events-http-specific.py | 42 | ||||
-rw-r--r-- | examples/addons/events-tcp-specific.py | 25 | ||||
-rw-r--r-- | examples/addons/events-websocket-specific.py | 36 | ||||
-rw-r--r-- | examples/addons/events.py | 93 | ||||
-rw-r--r-- | examples/complex/websocket_inject_message.py | 2 | ||||
-rw-r--r-- | examples/simple/websocket_messages.py | 11 |
10 files changed, 155 insertions, 115 deletions
diff --git a/docs/src/content/addons-events.md b/docs/src/content/addons-events.md index 489ea342..ddf0a99f 100644 --- a/docs/src/content/addons-events.md +++ b/docs/src/content/addons-events.md @@ -21,4 +21,18 @@ header with a count of the number of responses seen: Below is an addon class that implements stubs for all events. We've added annotations to illustrate the argument types for the various events. -{{< example src="examples/addons/events.py" lang="py" >}}
\ No newline at end of file +### Generic Events + +{{< example src="examples/addons/events.py" lang="py" >}} + +### HTTP Events + +{{< example src="examples/addons/events-http-specific.py" lang="py" >}} + +### WebSocket Events + +{{< example src="examples/addons/events-websocket-specific.py" lang="py" >}} + +### TCP Events + +{{< example src="examples/addons/events-tcp-specific.py" lang="py" >}} diff --git a/docs/src/content/addons-scripting.md b/docs/src/content/addons-scripting.md index 6a18eaf4..c90a9037 100644 --- a/docs/src/content/addons-scripting.md +++ b/docs/src/content/addons-scripting.md @@ -5,7 +5,7 @@ menu: weight: 5 --- -# Scripting +# Scripting HTTP/1.1 and HTTP/2.0 Sometimes, we would like to write a quick script without going through the trouble of creating a class. The addons mechanism has a shorthand that allows a @@ -13,7 +13,6 @@ module as a whole to be treated as an addon object. This lets us place event handler functions in the module scope. For instance, here is a complete script that adds a header to every request. - {{< example src="examples/addons/scripting-headers.py" lang="py" >}} @@ -22,11 +21,31 @@ an arbitrary response instead: {{< example src="examples/simple/send_reply_from_proxy.py" lang="py" >}} +All events around the HTTP protocol [can be found here]({{< relref "addons-events#http-events">}}). -You can look at the [http][] module, or the [Request][], and -[Response][] classes for other attributes that you can use when +For HTTP-related objects, please look at the [http][] module, or the +[Request][], and [Response][] classes for other attributes that you can use when scripting. -[http]: https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/http.py -[Request]: https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/net/http/request.py -[Response]: https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/net/http/response.py +# Scripting WebSocket + +The WebSocket protocol initially looks like a regular HTTP request, before the client and server agree to upgrade the connection to WebSocket. All scripting events for initial HTTP handshake, and also the dedicated WebSocket events [can be found here]({{< relref "addons-events#websocket-events">}}). + +{{< example src="examples/simple/websocket_messages.py" lang="py" >}} + +For WebSocket-related objects please look at the [websocket][] module to find +all attributes that you can use when scripting. + +[websocket]: https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/websocket.py + + +# Scripting TCP + +All events around the TCP protocol [can be found here]({{< relref "addons-events#tcp-events">}}). + +{{< example src="examples/complex/tcp_message.py" lang="py" >}} + +For WebSocket-related objects please look at the [tcp][] module to find +all attributes that you can use when scripting. + +[tcp]: https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/tcp.py diff --git a/docs/src/content/concepts-commands.md b/docs/src/content/concepts-commands.md index 72f17252..46d76209 100644 --- a/docs/src/content/concepts-commands.md +++ b/docs/src/content/concepts-commands.md @@ -60,13 +60,3 @@ just replay flows for a specific domain: {{< highlight none >}} :replay.client "~d google.com" {{< /highlight >}} - - - - - - - - - - diff --git a/docs/src/themes/mitmproxydocs/layouts/partials/header.html b/docs/src/themes/mitmproxydocs/layouts/partials/header.html index 1dcf3a23..925631d6 100644 --- a/docs/src/themes/mitmproxydocs/layouts/partials/header.html +++ b/docs/src/themes/mitmproxydocs/layouts/partials/header.html @@ -20,6 +20,6 @@ {{ if .RSSLink -}} <link href="{{ .RSSLink }}" rel="feed" type="application/rss+xml" title="{{ .Site.Title }}"> {{- end }} - {{ .Hugo.Generator }} + {{ hugo.Generator }} </head> <body> diff --git a/examples/addons/events-http-specific.py b/examples/addons/events-http-specific.py new file mode 100644 index 00000000..37d9f91a --- /dev/null +++ b/examples/addons/events-http-specific.py @@ -0,0 +1,42 @@ +import mitmproxy.http + + +class Events: + # HTTP lifecycle + def http_connect(self, flow: mitmproxy.http.HTTPFlow): + """ + An HTTP CONNECT request was received. Setting a non 2xx response on + the flow will return the response to the client abort the + connection. CONNECT requests and responses do not generate the usual + HTTP handler events. CONNECT requests are only valid in regular and + upstream proxy modes. + """ + + def requestheaders(self, flow: mitmproxy.http.HTTPFlow): + """ + HTTP request headers were successfully read. At this point, the body + is empty. + """ + + def request(self, flow: mitmproxy.http.HTTPFlow): + """ + The full HTTP request has been read. + """ + + def responseheaders(self, flow: mitmproxy.http.HTTPFlow): + """ + HTTP response headers were successfully read. At this point, the body + is empty. + """ + + def response(self, flow: mitmproxy.http.HTTPFlow): + """ + The full HTTP response has been read. + """ + + def error(self, flow: mitmproxy.http.HTTPFlow): + """ + An HTTP error has occurred, e.g. invalid server responses, or + interrupted connections. This is distinct from a valid server HTTP + error response, which is simply a response with an HTTP error code. + """ diff --git a/examples/addons/events-tcp-specific.py b/examples/addons/events-tcp-specific.py new file mode 100644 index 00000000..d150d0f9 --- /dev/null +++ b/examples/addons/events-tcp-specific.py @@ -0,0 +1,25 @@ +import mitmproxy.tcp + + +class Events: + # TCP lifecycle + def tcp_start(self, flow: mitmproxy.tcp.TCPFlow): + """ + A TCP connection has started. + """ + + def tcp_message(self, flow: mitmproxy.tcp.TCPFlow): + """ + A TCP connection has received a message. The most recent message + will be flow.messages[-1]. The message is user-modifiable. + """ + + def tcp_error(self, flow: mitmproxy.tcp.TCPFlow): + """ + A TCP error has occurred. + """ + + def tcp_end(self, flow: mitmproxy.tcp.TCPFlow): + """ + A TCP connection has ended. + """ diff --git a/examples/addons/events-websocket-specific.py b/examples/addons/events-websocket-specific.py new file mode 100644 index 00000000..60069fdb --- /dev/null +++ b/examples/addons/events-websocket-specific.py @@ -0,0 +1,36 @@ +import mitmproxy.http +import mitmproxy.websocket + + +class Events: + # Websocket lifecycle + def websocket_handshake(self, flow: mitmproxy.http.HTTPFlow): + """ + Called when a client wants to establish a WebSocket connection. The + WebSocket-specific headers can be manipulated to alter the + handshake. The flow object is guaranteed to have a non-None request + attribute. + """ + + def websocket_start(self, flow: mitmproxy.websocket.WebSocketFlow): + """ + A websocket connection has commenced. + """ + + def websocket_message(self, flow: mitmproxy.websocket.WebSocketFlow): + """ + Called when a WebSocket message is received from the client or + server. The most recent message will be flow.messages[-1]. The + message is user-modifiable. Currently there are two types of + messages, corresponding to the BINARY and TEXT frame types. + """ + + def websocket_error(self, flow: mitmproxy.websocket.WebSocketFlow): + """ + A websocket connection has had an error. + """ + + def websocket_end(self, flow: mitmproxy.websocket.WebSocketFlow): + """ + A websocket connection has ended. + """ diff --git a/examples/addons/events.py b/examples/addons/events.py index f83c8f11..958e7d39 100644 --- a/examples/addons/events.py +++ b/examples/addons/events.py @@ -10,99 +10,6 @@ import mitmproxy.proxy.protocol class Events: - # HTTP lifecycle - def http_connect(self, flow: mitmproxy.http.HTTPFlow): - """ - An HTTP CONNECT request was received. Setting a non 2xx response on - the flow will return the response to the client abort the - connection. CONNECT requests and responses do not generate the usual - HTTP handler events. CONNECT requests are only valid in regular and - upstream proxy modes. - """ - - def requestheaders(self, flow: mitmproxy.http.HTTPFlow): - """ - HTTP request headers were successfully read. At this point, the body - is empty. - """ - - def request(self, flow: mitmproxy.http.HTTPFlow): - """ - The full HTTP request has been read. - """ - - def responseheaders(self, flow: mitmproxy.http.HTTPFlow): - """ - HTTP response headers were successfully read. At this point, the body - is empty. - """ - - def response(self, flow: mitmproxy.http.HTTPFlow): - """ - The full HTTP response has been read. - """ - - def error(self, flow: mitmproxy.http.HTTPFlow): - """ - An HTTP error has occurred, e.g. invalid server responses, or - interrupted connections. This is distinct from a valid server HTTP - error response, which is simply a response with an HTTP error code. - """ - - # TCP lifecycle - def tcp_start(self, flow: mitmproxy.tcp.TCPFlow): - """ - A TCP connection has started. - """ - - def tcp_message(self, flow: mitmproxy.tcp.TCPFlow): - """ - A TCP connection has received a message. The most recent message - will be flow.messages[-1]. The message is user-modifiable. - """ - - def tcp_error(self, flow: mitmproxy.tcp.TCPFlow): - """ - A TCP error has occurred. - """ - - def tcp_end(self, flow: mitmproxy.tcp.TCPFlow): - """ - A TCP connection has ended. - """ - - # Websocket lifecycle - def websocket_handshake(self, flow: mitmproxy.http.HTTPFlow): - """ - Called when a client wants to establish a WebSocket connection. The - WebSocket-specific headers can be manipulated to alter the - handshake. The flow object is guaranteed to have a non-None request - attribute. - """ - - def websocket_start(self, flow: mitmproxy.websocket.WebSocketFlow): - """ - A websocket connection has commenced. - """ - - def websocket_message(self, flow: mitmproxy.websocket.WebSocketFlow): - """ - Called when a WebSocket message is received from the client or - server. The most recent message will be flow.messages[-1]. The - message is user-modifiable. Currently there are two types of - messages, corresponding to the BINARY and TEXT frame types. - """ - - def websocket_error(self, flow: mitmproxy.websocket.WebSocketFlow): - """ - A websocket connection has had an error. - """ - - def websocket_end(self, flow: mitmproxy.websocket.WebSocketFlow): - """ - A websocket connection has ended. - """ - # Network lifecycle def clientconnect(self, layer: mitmproxy.proxy.protocol.Layer): """ diff --git a/examples/complex/websocket_inject_message.py b/examples/complex/websocket_inject_message.py index e9c3ea0c..38be5555 100644 --- a/examples/complex/websocket_inject_message.py +++ b/examples/complex/websocket_inject_message.py @@ -13,7 +13,7 @@ class InjectWebSocketMessage: i = 0 while not flow.ended and not flow.error: await asyncio.sleep(5) - flow.inject_message(flow.client_conn, 'This is the #{} an injected message!'.format(i)) + flow.inject_message(flow.client_conn, 'This is the #{} injected message!'.format(i)) i += 1 def websocket_start(self, flow): diff --git a/examples/simple/websocket_messages.py b/examples/simple/websocket_messages.py index 719e7b10..071ea21f 100644 --- a/examples/simple/websocket_messages.py +++ b/examples/simple/websocket_messages.py @@ -6,8 +6,15 @@ def websocket_message(flow): # get the latest message message = flow.messages[-1] - # simply print the content of the message - ctx.log.info(message.content) + # was the message sent from the client or server? + if message.from_client: + ctx.log.info("Client sent a message: {}".format(message.content)) + else: + ctx.log.info("Server sent a message: {}".format(message.content)) # manipulate the message content message.content = re.sub(r'^Hello', 'HAPPY', message.content) + + if 'FOOBAR' in message.content: + # kill the message and not send it to the other endpoint + message.kill() |