diff --git a/docs/scripts/api-render.py b/docs/scripts/api-render.py index f7c58d091..a293db7dd 100644 --- a/docs/scripts/api-render.py +++ b/docs/scripts/api-render.py @@ -30,8 +30,10 @@ modules = [ "mitmproxy.flow", "mitmproxy.http", "mitmproxy.net.server_spec", + "mitmproxy.proxy.context", "mitmproxy.proxy.server_hooks", "mitmproxy.tcp", + "mitmproxy.tls", "mitmproxy.websocket", here / ".." / "src" / "generated" / "events.py", ] diff --git a/docs/scripts/pdoc-template/module.html.jinja2 b/docs/scripts/pdoc-template/module.html.jinja2 index 268c393fb..d6d731c24 100644 --- a/docs/scripts/pdoc-template/module.html.jinja2 +++ b/docs/scripts/pdoc-template/module.html.jinja2 @@ -55,6 +55,14 @@ To document all event hooks, we do a bit of hackery: {% if doc.qualname.startswith("ServerConnectionHookData") and doc.name != "__init__" %} {{ default_is_public(doc) }} {% endif %} + {% elif doc.modulename == "mitmproxy.proxy.context" %} + {% if doc.qualname is not in(["Context.__init__", "Context.fork", "Context.options"]) %} + {{ default_is_public(doc) }} + {% endif %} + {% elif doc.modulename == "mitmproxy.tls" %} + {% if doc.qualname is not in(["TlsData.__init__", "ClientHelloData.__init__"]) %} + {{ default_is_public(doc) }} + {% endif %} {% elif doc.modulename == "mitmproxy.websocket" %} {% if doc.qualname != "WebSocketMessage.type" %} {{ default_is_public(doc) }} diff --git a/docs/src/content/api/mitmproxy.proxy.context.md b/docs/src/content/api/mitmproxy.proxy.context.md new file mode 100644 index 000000000..b4aa48865 --- /dev/null +++ b/docs/src/content/api/mitmproxy.proxy.context.md @@ -0,0 +1,11 @@ + +--- +title: "mitmproxy.proxy.context" +url: "api/mitmproxy/proxy/context.html" + +menu: + addons: + parent: 'Event Hooks & API' +--- + +{{< readfile file="/generated/api/mitmproxy/proxy/context.html" >}} diff --git a/docs/src/content/api/mitmproxy.tls.md b/docs/src/content/api/mitmproxy.tls.md new file mode 100644 index 000000000..02dcbeb30 --- /dev/null +++ b/docs/src/content/api/mitmproxy.tls.md @@ -0,0 +1,11 @@ + +--- +title: "mitmproxy.tls" +url: "api/mitmproxy/tls.html" + +menu: + addons: + parent: 'Event Hooks & API' +--- + +{{< readfile file="/generated/api/mitmproxy/tls.html" >}} diff --git a/mitmproxy/proxy/context.py b/mitmproxy/proxy/context.py index 0114c00c5..8f8025b9f 100644 --- a/mitmproxy/proxy/context.py +++ b/mitmproxy/proxy/context.py @@ -9,13 +9,26 @@ if TYPE_CHECKING: class Context: """ - The context object provided to each `mitmproxy.proxy.layer.Layer` by its parent layer. + The context object provided to each protocol layer in the proxy core. """ client: connection.Client + """The client connection.""" server: connection.Server + """ + The server connection. + + For practical reasons this attribute is always set, even if there is not server connection yet. + In this case the server address is `None`. + """ options: Options + """ + Provides access to options for proxy layers. Not intended for use by addons, use `mitmproxy.ctx.options` instead. + """ layers: List["mitmproxy.proxy.layer.Layer"] + """ + The protocol layer stack. + """ def __init__( self, diff --git a/mitmproxy/tls.py b/mitmproxy/tls.py index 55b14668b..31b607107 100644 --- a/mitmproxy/tls.py +++ b/mitmproxy/tls.py @@ -16,17 +16,23 @@ class ClientHello: A TLS ClientHello is the first message sent by the client when initiating TLS. """ - def __init__(self, raw_client_hello): + def __init__(self, raw_client_hello: bytes): + """Create a TLS ClientHello object from raw bytes.""" self._client_hello = tls_client_hello.TlsClientHello( KaitaiStream(io.BytesIO(raw_client_hello)) ) @property def cipher_suites(self) -> List[int]: + """The cipher suites offered by the client (as raw ints).""" return self._client_hello.cipher_suites.cipher_suites @property def sni(self) -> Optional[str]: + """ + The [Server Name Indication](https://en.wikipedia.org/wiki/Server_Name_Indication), + which indicates which hostname the client wants to connect to. + """ if self._client_hello.extensions: for extension in self._client_hello.extensions.extensions: is_valid_sni_extension = ( @@ -41,6 +47,10 @@ class ClientHello: @property def alpn_protocols(self) -> List[bytes]: + """ + The application layer protocols offered by the client as part of the + [ALPN](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation) TLS extension. + """ if self._client_hello.extensions: for extension in self._client_hello.extensions.extensions: if extension.type == 0x10: @@ -49,6 +59,7 @@ class ClientHello: @property def extensions(self) -> List[Tuple[int, bytes]]: + """The raw list of extensions in the form of `(extension_type, raw_bytes)` tuples.""" ret = [] if self._client_hello.extensions: for extension in self._client_hello.extensions.extensions: