mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-22 15:37:45 +00:00
Merge pull request #3898 from Kriechi/websocket-docs
improve scripting docs
This commit is contained in:
commit
ac83db3b84
@ -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
|
Below is an addon class that implements stubs for all events. We've added
|
||||||
annotations to illustrate the argument types for the various events.
|
annotations to illustrate the argument types for the various events.
|
||||||
|
|
||||||
|
### Generic Events
|
||||||
|
|
||||||
{{< example src="examples/addons/events.py" lang="py" >}}
|
{{< 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" >}}
|
||||||
|
@ -5,7 +5,7 @@ menu:
|
|||||||
weight: 5
|
weight: 5
|
||||||
---
|
---
|
||||||
|
|
||||||
# Scripting
|
# Scripting HTTP/1.1 and HTTP/2.0
|
||||||
|
|
||||||
Sometimes, we would like to write a quick script without going through the
|
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
|
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
|
handler functions in the module scope. For instance, here is a complete script
|
||||||
that adds a header to every request.
|
that adds a header to every request.
|
||||||
|
|
||||||
|
|
||||||
{{< example src="examples/addons/scripting-headers.py" lang="py" >}}
|
{{< 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" >}}
|
{{< 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
|
For HTTP-related objects, please look at the [http][] module, or the
|
||||||
[Response][] classes for other attributes that you can use when
|
[Request][], and [Response][] classes for other attributes that you can use when
|
||||||
scripting.
|
scripting.
|
||||||
|
|
||||||
[http]: https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/http.py
|
# Scripting WebSocket
|
||||||
[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
|
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
|
||||||
|
@ -60,13 +60,3 @@ just replay flows for a specific domain:
|
|||||||
{{< highlight none >}}
|
{{< highlight none >}}
|
||||||
:replay.client "~d google.com"
|
:replay.client "~d google.com"
|
||||||
{{< /highlight >}}
|
{{< /highlight >}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,6 @@
|
|||||||
{{ if .RSSLink -}}
|
{{ if .RSSLink -}}
|
||||||
<link href="{{ .RSSLink }}" rel="feed" type="application/rss+xml" title="{{ .Site.Title }}">
|
<link href="{{ .RSSLink }}" rel="feed" type="application/rss+xml" title="{{ .Site.Title }}">
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{ .Hugo.Generator }}
|
{{ hugo.Generator }}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
42
examples/addons/events-http-specific.py
Normal file
42
examples/addons/events-http-specific.py
Normal file
@ -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.
|
||||||
|
"""
|
25
examples/addons/events-tcp-specific.py
Normal file
25
examples/addons/events-tcp-specific.py
Normal file
@ -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.
|
||||||
|
"""
|
36
examples/addons/events-websocket-specific.py
Normal file
36
examples/addons/events-websocket-specific.py
Normal file
@ -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.
|
||||||
|
"""
|
@ -10,99 +10,6 @@ import mitmproxy.proxy.protocol
|
|||||||
|
|
||||||
|
|
||||||
class Events:
|
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
|
# Network lifecycle
|
||||||
def clientconnect(self, layer: mitmproxy.proxy.protocol.Layer):
|
def clientconnect(self, layer: mitmproxy.proxy.protocol.Layer):
|
||||||
"""
|
"""
|
||||||
|
@ -13,7 +13,7 @@ class InjectWebSocketMessage:
|
|||||||
i = 0
|
i = 0
|
||||||
while not flow.ended and not flow.error:
|
while not flow.ended and not flow.error:
|
||||||
await asyncio.sleep(5)
|
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
|
i += 1
|
||||||
|
|
||||||
def websocket_start(self, flow):
|
def websocket_start(self, flow):
|
||||||
|
@ -6,8 +6,15 @@ def websocket_message(flow):
|
|||||||
# get the latest message
|
# get the latest message
|
||||||
message = flow.messages[-1]
|
message = flow.messages[-1]
|
||||||
|
|
||||||
# simply print the content of the message
|
# was the message sent from the client or server?
|
||||||
ctx.log.info(message.content)
|
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
|
# manipulate the message content
|
||||||
message.content = re.sub(r'^Hello', 'HAPPY', 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()
|
||||||
|
Loading…
Reference in New Issue
Block a user