aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/src/content/addons-events.md16
-rw-r--r--docs/src/content/addons-scripting.md33
-rw-r--r--docs/src/content/concepts-commands.md10
-rw-r--r--docs/src/themes/mitmproxydocs/layouts/partials/header.html2
-rw-r--r--examples/addons/events-http-specific.py42
-rw-r--r--examples/addons/events-tcp-specific.py25
-rw-r--r--examples/addons/events-websocket-specific.py36
-rw-r--r--examples/addons/events.py93
-rw-r--r--examples/complex/websocket_inject_message.py2
-rw-r--r--examples/simple/websocket_messages.py11
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()