mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-25 09:37:37 +00:00
docs: first prototype to link from events to API reference
This commit is contained in:
parent
09beb1aa13
commit
a7d1f32c89
17
docs/build.py
Normal file
17
docs/build.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
here = Path(__file__).parent
|
||||||
|
|
||||||
|
for script in (here / "scripts").glob("*.py"):
|
||||||
|
print(f"Generating output for {script.name}...")
|
||||||
|
out = subprocess.check_output(["python3", script.absolute()], text=True)
|
||||||
|
if out:
|
||||||
|
(here / "src" / "generated" / f"{script.stem}.html").write_text(out)
|
||||||
|
|
||||||
|
if (here / "public").exists():
|
||||||
|
shutil.rmtree(here / "public")
|
||||||
|
subprocess.run(["hugo"], cwd=here / "src")
|
@ -1,20 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -o errexit
|
|
||||||
set -o pipefail
|
|
||||||
set -o nounset
|
|
||||||
# set -o xtrace
|
|
||||||
|
|
||||||
SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
|
|
||||||
pushd ${SCRIPTPATH}
|
|
||||||
|
|
||||||
for script in scripts/*.py ; do
|
|
||||||
output="${script##*/}"
|
|
||||||
output="src/generated/${output%.*}.html"
|
|
||||||
echo "Generating output for ${script} into ${output} ..."
|
|
||||||
"${script}" > "${output}"
|
|
||||||
done
|
|
||||||
|
|
||||||
rm -rf ./public
|
|
||||||
cd src
|
|
||||||
hugo
|
|
@ -1,5 +1,5 @@
|
|||||||
scripts/*.py {
|
scripts/** {
|
||||||
prep: ./build.sh
|
prep: python3 build.py
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
142
docs/scripts/api-events.py
Normal file
142
docs/scripts/api-events.py
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import contextlib
|
||||||
|
import inspect
|
||||||
|
import textwrap
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Type
|
||||||
|
|
||||||
|
import mitmproxy.addons.next_layer # noqa
|
||||||
|
from mitmproxy import hooks, log, addonmanager
|
||||||
|
from mitmproxy.proxy import server_hooks, layer
|
||||||
|
from mitmproxy.proxy.layers import http, tcp, tls, websocket
|
||||||
|
|
||||||
|
known = set()
|
||||||
|
|
||||||
|
|
||||||
|
def category(name: str, hooks: List[Type[hooks.Hook]]) -> None:
|
||||||
|
all_params = [
|
||||||
|
list(inspect.signature(hook.__init__).parameters.values())[1:]
|
||||||
|
for hook in hooks
|
||||||
|
]
|
||||||
|
|
||||||
|
# slightly overengineered, but this was fun to write. ¯\_(ツ)_/¯
|
||||||
|
imports = set()
|
||||||
|
types = set()
|
||||||
|
for params in all_params:
|
||||||
|
for param in params:
|
||||||
|
try:
|
||||||
|
mod = inspect.getmodule(param.annotation).__name__
|
||||||
|
if mod == "typing":
|
||||||
|
# this is ugly, but can be removed once we are on Python 3.9+ only
|
||||||
|
imports.add(inspect.getmodule(param.annotation.__args__[0]).__name__)
|
||||||
|
types.add(param.annotation._name)
|
||||||
|
else:
|
||||||
|
imports.add(mod)
|
||||||
|
except AttributeError:
|
||||||
|
raise ValueError(f"Missing type annotation: {params}")
|
||||||
|
imports.discard("builtins")
|
||||||
|
if types:
|
||||||
|
print(f"from typing import {', '.join(sorted(types))}")
|
||||||
|
print("from mitmproxy import ctx")
|
||||||
|
for imp in sorted(imports):
|
||||||
|
print(f"import {imp}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print(f"class {name}_Events:")
|
||||||
|
|
||||||
|
first = True
|
||||||
|
for hook, params in zip(hooks, all_params):
|
||||||
|
if first:
|
||||||
|
first = False
|
||||||
|
else:
|
||||||
|
print()
|
||||||
|
if hook.name in known:
|
||||||
|
raise RuntimeError(f"Already documented: {hook}")
|
||||||
|
known.add(hook.name)
|
||||||
|
doc = inspect.getdoc(hook)
|
||||||
|
print(f" def {hook.name}({', '.join(str(p) for p in params)}):")
|
||||||
|
print(textwrap.indent(f'"""\n{doc}\n"""', " "))
|
||||||
|
if params:
|
||||||
|
print(f' ctx.log(f"{hook.name}: {" ".join("{" + p.name + "=}" for p in params)}")')
|
||||||
|
else:
|
||||||
|
print(f' ctx.log("{hook.name}")')
|
||||||
|
print("")
|
||||||
|
|
||||||
|
|
||||||
|
outfile = Path(__file__).parent.parent / "src" / "generated" / "events.py"
|
||||||
|
|
||||||
|
with outfile.open("w") as f, contextlib.redirect_stdout(f):
|
||||||
|
|
||||||
|
category(
|
||||||
|
"Lifecycle",
|
||||||
|
[
|
||||||
|
addonmanager.LoadHook,
|
||||||
|
hooks.RunningHook,
|
||||||
|
hooks.ConfigureHook,
|
||||||
|
hooks.DoneHook,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
category(
|
||||||
|
"Connection",
|
||||||
|
[
|
||||||
|
server_hooks.ClientConnectedHook,
|
||||||
|
server_hooks.ClientDisconnectedHook,
|
||||||
|
server_hooks.ServerConnectHook,
|
||||||
|
server_hooks.ServerConnectedHook,
|
||||||
|
server_hooks.ServerDisconnectedHook,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
category(
|
||||||
|
"HTTP",
|
||||||
|
[
|
||||||
|
http.HttpRequestHeadersHook,
|
||||||
|
http.HttpRequestHook,
|
||||||
|
http.HttpResponseHeadersHook,
|
||||||
|
http.HttpResponseHook,
|
||||||
|
http.HttpErrorHook,
|
||||||
|
http.HttpConnectHook,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
category(
|
||||||
|
"TCP",
|
||||||
|
[
|
||||||
|
tcp.TcpStartHook,
|
||||||
|
tcp.TcpMessageHook,
|
||||||
|
tcp.TcpEndHook,
|
||||||
|
tcp.TcpErrorHook,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
category(
|
||||||
|
"TLS",
|
||||||
|
[
|
||||||
|
tls.TlsClienthelloHook,
|
||||||
|
tls.TlsStartHook,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
category(
|
||||||
|
"WebSocket",
|
||||||
|
[
|
||||||
|
websocket.WebsocketStartHook,
|
||||||
|
websocket.WebsocketMessageHook,
|
||||||
|
websocket.WebsocketEndHook,
|
||||||
|
websocket.WebsocketErrorHook,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
category(
|
||||||
|
"Advanced_Lifecycle",
|
||||||
|
[
|
||||||
|
layer.NextLayerHook,
|
||||||
|
hooks.UpdateHook,
|
||||||
|
log.AddLogHook,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
not_documented = set(hooks.all_hooks.keys()) - known
|
||||||
|
if not_documented:
|
||||||
|
raise RuntimeError(f"Not documented: {not_documented}")
|
17
docs/scripts/api.py → docs/scripts/api-render.py
Executable file → Normal file
17
docs/scripts/api.py → docs/scripts/api-render.py
Executable file → Normal file
@ -20,6 +20,7 @@ pdoc.render.configure(
|
|||||||
)
|
)
|
||||||
|
|
||||||
modules = [
|
modules = [
|
||||||
|
here / ".." / "src" / "generated" / "events.py",
|
||||||
"mitmproxy.proxy.context",
|
"mitmproxy.proxy.context",
|
||||||
"mitmproxy.http",
|
"mitmproxy.http",
|
||||||
"mitmproxy.flow",
|
"mitmproxy.flow",
|
||||||
@ -39,6 +40,8 @@ if api_content.exists():
|
|||||||
api_content.mkdir()
|
api_content.mkdir()
|
||||||
|
|
||||||
for module in modules:
|
for module in modules:
|
||||||
|
if isinstance(module, Path):
|
||||||
|
continue
|
||||||
filename = f"api/{ module.replace('.','/') }.html"
|
filename = f"api/{ module.replace('.','/') }.html"
|
||||||
(api_content / f"{module}.md").write_text(f"""
|
(api_content / f"{module}.md").write_text(f"""
|
||||||
---
|
---
|
||||||
@ -47,20 +50,8 @@ url: "{filename}"
|
|||||||
|
|
||||||
menu:
|
menu:
|
||||||
addons:
|
addons:
|
||||||
parent: 'API Reference'
|
parent: 'API'
|
||||||
---
|
---
|
||||||
|
|
||||||
{{{{< readfile file="/generated/{filename}" >}}}}
|
{{{{< readfile file="/generated/{filename}" >}}}}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
(api_content / f"_index.md").write_text(f"""
|
|
||||||
---
|
|
||||||
title: "API Reference"
|
|
||||||
layout: single
|
|
||||||
menu:
|
|
||||||
addons:
|
|
||||||
weight: 5
|
|
||||||
---
|
|
||||||
|
|
||||||
# API Reference
|
|
||||||
""")
|
|
@ -1,142 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
import inspect
|
|
||||||
import textwrap
|
|
||||||
from typing import List, Type
|
|
||||||
|
|
||||||
import mitmproxy.addons.next_layer # noqa
|
|
||||||
from mitmproxy import hooks, log, addonmanager
|
|
||||||
from mitmproxy.proxy import server_hooks, layer
|
|
||||||
from mitmproxy.proxy.layers import http, tcp, tls, websocket
|
|
||||||
|
|
||||||
known = set()
|
|
||||||
|
|
||||||
|
|
||||||
def category(name: str, hooks: List[Type[hooks.Hook]]) -> None:
|
|
||||||
print(f"### {name} Events")
|
|
||||||
print("```python")
|
|
||||||
|
|
||||||
all_params = [
|
|
||||||
list(inspect.signature(hook.__init__).parameters.values())[1:]
|
|
||||||
for hook in hooks
|
|
||||||
]
|
|
||||||
|
|
||||||
# slightly overengineered, but this was fun to write. ¯\_(ツ)_/¯
|
|
||||||
imports = set()
|
|
||||||
types = set()
|
|
||||||
for params in all_params:
|
|
||||||
for param in params:
|
|
||||||
try:
|
|
||||||
mod = inspect.getmodule(param.annotation).__name__
|
|
||||||
if mod == "typing":
|
|
||||||
# this is ugly, but can be removed once we are on Python 3.9+ only
|
|
||||||
imports.add(inspect.getmodule(param.annotation.__args__[0]).__name__)
|
|
||||||
types.add(param.annotation._name)
|
|
||||||
else:
|
|
||||||
imports.add(mod)
|
|
||||||
except AttributeError:
|
|
||||||
raise ValueError(f"Missing type annotation: {params}")
|
|
||||||
imports.discard("builtins")
|
|
||||||
if types:
|
|
||||||
print(f"from typing import {', '.join(sorted(types))}")
|
|
||||||
print("from mitmproxy import ctx")
|
|
||||||
for imp in sorted(imports):
|
|
||||||
print(f"import {imp}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
first = True
|
|
||||||
for hook, params in zip(hooks, all_params):
|
|
||||||
if first:
|
|
||||||
first = False
|
|
||||||
else:
|
|
||||||
print()
|
|
||||||
if hook.name in known:
|
|
||||||
raise RuntimeError(f"Already documented: {hook}")
|
|
||||||
known.add(hook.name)
|
|
||||||
doc = inspect.getdoc(hook)
|
|
||||||
print(f"def {hook.name}({', '.join(str(p) for p in params)}):")
|
|
||||||
print(textwrap.indent(f'"""\n{doc}\n"""', " "))
|
|
||||||
if params:
|
|
||||||
print(f' ctx.log(f"{hook.name}: {" ".join("{" + p.name + "=}" for p in params)}")')
|
|
||||||
else:
|
|
||||||
print(f' ctx.log("{hook.name}")')
|
|
||||||
print("```")
|
|
||||||
|
|
||||||
|
|
||||||
category(
|
|
||||||
"Lifecycle",
|
|
||||||
[
|
|
||||||
addonmanager.LoadHook,
|
|
||||||
hooks.RunningHook,
|
|
||||||
hooks.ConfigureHook,
|
|
||||||
hooks.DoneHook,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
category(
|
|
||||||
"Connection",
|
|
||||||
[
|
|
||||||
server_hooks.ClientConnectedHook,
|
|
||||||
server_hooks.ClientDisconnectedHook,
|
|
||||||
server_hooks.ServerConnectHook,
|
|
||||||
server_hooks.ServerConnectedHook,
|
|
||||||
server_hooks.ServerDisconnectedHook,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
category(
|
|
||||||
"HTTP",
|
|
||||||
[
|
|
||||||
http.HttpRequestHeadersHook,
|
|
||||||
http.HttpRequestHook,
|
|
||||||
http.HttpResponseHeadersHook,
|
|
||||||
http.HttpResponseHook,
|
|
||||||
http.HttpErrorHook,
|
|
||||||
http.HttpConnectHook,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
category(
|
|
||||||
"TCP",
|
|
||||||
[
|
|
||||||
tcp.TcpStartHook,
|
|
||||||
tcp.TcpMessageHook,
|
|
||||||
tcp.TcpEndHook,
|
|
||||||
tcp.TcpErrorHook,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
category(
|
|
||||||
"TLS",
|
|
||||||
[
|
|
||||||
tls.TlsClienthelloHook,
|
|
||||||
tls.TlsStartHook,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
category(
|
|
||||||
"WebSocket",
|
|
||||||
[
|
|
||||||
websocket.WebsocketStartHook,
|
|
||||||
websocket.WebsocketMessageHook,
|
|
||||||
websocket.WebsocketEndHook,
|
|
||||||
websocket.WebsocketErrorHook,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
category(
|
|
||||||
"Advanced Lifecycle",
|
|
||||||
[
|
|
||||||
layer.NextLayerHook,
|
|
||||||
hooks.UpdateHook,
|
|
||||||
log.AddLogHook,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
not_documented = set(hooks.all_hooks.keys()) - known
|
|
||||||
if not_documented:
|
|
||||||
raise RuntimeError(f"Not documented: {not_documented}")
|
|
||||||
|
|
||||||
# print("<table class=\"table filtertable\"><tbody>")
|
|
||||||
# for i in flowfilter.help:
|
|
||||||
# print("<tr><th>%s</th><td>%s</td></tr>" % i)
|
|
||||||
# print("</tbody></table>")
|
|
@ -1,3 +1,36 @@
|
|||||||
{% extends "default/module.html.jinja2" %}
|
{% extends "default/module.html.jinja2" %}
|
||||||
{% block nav %}{% endblock %}
|
{% block nav %}{% endblock %}
|
||||||
{% block style_layout %}{% endblock %}
|
{% block style_layout %}{% endblock %}
|
||||||
|
|
||||||
|
{#
|
||||||
|
We do a bit of hackery here: generated/events.py is automatically created by scripts/api-events.py,
|
||||||
|
and then documented using a heavily customized style.
|
||||||
|
#}
|
||||||
|
{% if module.name == "events" %}
|
||||||
|
{% macro module_name() %}
|
||||||
|
<style type="text/css">
|
||||||
|
.pdoc .classattr {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endmacro %}
|
||||||
|
{% macro view_source(doc) %}
|
||||||
|
{% if doc.type == "function" %}
|
||||||
|
<details>
|
||||||
|
<summary>View Source</summary>
|
||||||
|
{{ doc.source | dedent | highlight }}
|
||||||
|
</details>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
{% macro is_public(doc) %}
|
||||||
|
{% if doc.name != "__init__" %}
|
||||||
|
{{ default_is_public(doc) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
{% macro class(cls) %}
|
||||||
|
<h3>
|
||||||
|
{{ headerlink(cls) }}
|
||||||
|
<strong>{{ cls.name.replace("_", " ") }}</strong>
|
||||||
|
</h3>
|
||||||
|
{% endmacro %}
|
||||||
|
{% endif %}
|
||||||
|
@ -7,6 +7,9 @@ $family-sans-serif: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Ox
|
|||||||
|
|
||||||
$panel-heading-size: 1em;
|
$panel-heading-size: 1em;
|
||||||
$panel-heading-weight: 600;
|
$panel-heading-weight: 600;
|
||||||
|
$menu-list-link-padding: .3em .75em;
|
||||||
|
$menu-label-spacing: .7em;
|
||||||
|
$menu-nested-list-margin: .3em .75em;
|
||||||
|
|
||||||
/*!*
|
/*!*
|
||||||
bulma.io v0.8.0 | MIT License | github.com/jgthms/bulma */
|
bulma.io v0.8.0 | MIT License | github.com/jgthms/bulma */
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
---
|
---
|
||||||
title: "Event Hooks"
|
title: "API"
|
||||||
|
url: "api/events.html"
|
||||||
|
aliases:
|
||||||
|
- /addons-events/
|
||||||
|
layout: single
|
||||||
menu:
|
menu:
|
||||||
addons:
|
addons:
|
||||||
weight: 2
|
weight: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
|
# Mitmproxy API
|
||||||
|
|
||||||
|
TODO: Some more text here.
|
||||||
|
|
||||||
|
|
||||||
# Event Hooks
|
# Event Hooks
|
||||||
|
|
||||||
Addons hook into mitmproxy's internal mechanisms through event hooks. These are
|
Addons hook into mitmproxy's internal mechanisms through event hooks. These are
|
||||||
@ -16,9 +25,7 @@ header with a count of the number of responses seen:
|
|||||||
{{< example src="examples/addons/http-add-header.py" lang="py" >}}
|
{{< example src="examples/addons/http-add-header.py" lang="py" >}}
|
||||||
|
|
||||||
|
|
||||||
## Supported Events
|
## Addon Events
|
||||||
|
|
||||||
Below we list events supported by mitmproxy. We've added
|
|
||||||
annotations to illustrate the argument types.
|
|
||||||
|
|
||||||
{{< readfile file="/generated/events.html" markdown="true" >}}
|
{{< readfile file="/generated/api/events.html" >}}
|
@ -21,7 +21,7 @@ an arbitrary response instead:
|
|||||||
|
|
||||||
{{< example src="examples/addons/http-reply-from-proxy.py" lang="py" >}}
|
{{< example src="examples/addons/http-reply-from-proxy.py" lang="py" >}}
|
||||||
|
|
||||||
All events around the HTTP protocol [can be found here]({{< relref "addons-events#http-events">}}).
|
All events around the HTTP protocol [can be found here]({{< relref "addons-api#http-events">}}).
|
||||||
|
|
||||||
For HTTP-related objects, please look at the [http][] module, or the
|
For HTTP-related objects, please look at the [http][] module, or the
|
||||||
[Request][], and [Response][] classes for other attributes that you can use when
|
[Request][], and [Response][] classes for other attributes that you can use when
|
||||||
@ -29,7 +29,7 @@ scripting.
|
|||||||
|
|
||||||
# Scripting WebSocket
|
# 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">}}).
|
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-api#websocket-events">}}).
|
||||||
|
|
||||||
{{< example src="examples/addons/websocket-simple.py" lang="py" >}}
|
{{< example src="examples/addons/websocket-simple.py" lang="py" >}}
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ all attributes that you can use when scripting.
|
|||||||
|
|
||||||
# Scripting TCP
|
# Scripting TCP
|
||||||
|
|
||||||
All events around the TCP protocol [can be found here]({{< relref "addons-events#tcp-events">}}).
|
All events around the TCP protocol [can be found here]({{< relref "addons-api#tcp-events">}}).
|
||||||
|
|
||||||
{{< example src="examples/addons/tcp-simple.py" lang="py" >}}
|
{{< example src="examples/addons/tcp-simple.py" lang="py" >}}
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
---
|
|
||||||
title: "API Reference"
|
|
||||||
layout: single
|
|
||||||
menu:
|
|
||||||
addons:
|
|
||||||
weight: 5
|
|
||||||
---
|
|
||||||
|
|
||||||
# API Reference
|
|
@ -5,7 +5,7 @@ url: "api/mitmproxy/flow.html"
|
|||||||
|
|
||||||
menu:
|
menu:
|
||||||
addons:
|
addons:
|
||||||
parent: 'API Reference'
|
parent: 'API'
|
||||||
---
|
---
|
||||||
|
|
||||||
{{< readfile file="/generated/api/mitmproxy/flow.html" >}}
|
{{< readfile file="/generated/api/mitmproxy/flow.html" >}}
|
||||||
|
@ -5,7 +5,7 @@ url: "api/mitmproxy/http.html"
|
|||||||
|
|
||||||
menu:
|
menu:
|
||||||
addons:
|
addons:
|
||||||
parent: 'API Reference'
|
parent: 'API'
|
||||||
---
|
---
|
||||||
|
|
||||||
{{< readfile file="/generated/api/mitmproxy/http.html" >}}
|
{{< readfile file="/generated/api/mitmproxy/http.html" >}}
|
||||||
|
@ -5,7 +5,7 @@ url: "api/mitmproxy/proxy/context.html"
|
|||||||
|
|
||||||
menu:
|
menu:
|
||||||
addons:
|
addons:
|
||||||
parent: 'API Reference'
|
parent: 'API'
|
||||||
---
|
---
|
||||||
|
|
||||||
{{< readfile file="/generated/api/mitmproxy/proxy/context.html" >}}
|
{{< readfile file="/generated/api/mitmproxy/proxy/context.html" >}}
|
||||||
|
@ -5,7 +5,7 @@ url: "api/mitmproxy/tcp.html"
|
|||||||
|
|
||||||
menu:
|
menu:
|
||||||
addons:
|
addons:
|
||||||
parent: 'API Reference'
|
parent: 'API'
|
||||||
---
|
---
|
||||||
|
|
||||||
{{< readfile file="/generated/api/mitmproxy/tcp.html" >}}
|
{{< readfile file="/generated/api/mitmproxy/tcp.html" >}}
|
||||||
|
@ -5,7 +5,7 @@ url: "api/mitmproxy/websocket.html"
|
|||||||
|
|
||||||
menu:
|
menu:
|
||||||
addons:
|
addons:
|
||||||
parent: 'API Reference'
|
parent: 'API'
|
||||||
---
|
---
|
||||||
|
|
||||||
{{< readfile file="/generated/api/mitmproxy/websocket.html" >}}
|
{{< readfile file="/generated/api/mitmproxy/websocket.html" >}}
|
||||||
|
Loading…
Reference in New Issue
Block a user