2025-12-25 upload

This commit is contained in:
“shengyudong”
2025-12-25 11:16:59 +08:00
commit 322ac74336
2241 changed files with 639966 additions and 0 deletions

View File

@@ -0,0 +1,159 @@
"""
Commands make it possible for layers to communicate with the "outer world",
e.g. to perform IO or to ask the master.
A command is issued by a proxy layer and is then passed upwards to the proxy server, and from there
possibly to the master and addons.
The counterpart to commands are events.
"""
import logging
import warnings
from typing import TYPE_CHECKING
from typing import Union
import mitmproxy.hooks
from mitmproxy.connection import Connection
from mitmproxy.connection import Server
if TYPE_CHECKING:
import mitmproxy.proxy.layer
class Command:
"""
Base class for all commands
"""
blocking: Union[bool, "mitmproxy.proxy.layer.Layer"] = False
"""
Determines if the command blocks until it has been completed.
For practical purposes, this attribute should be thought of as a boolean value,
layers may swap out `True` with a reference to themselves to signal to outer layers
that they do not need to block as well.
Example:
reply = yield Hook("requestheaders", flow) # blocking command
yield Log("hello world", "info") # non-blocking
"""
def __repr__(self):
x = self.__dict__.copy()
x.pop("blocking", None)
return f"{type(self).__name__}({x!r})"
class RequestWakeup(Command):
"""
Request a `Wakeup` event after the specified amount of seconds.
"""
delay: float
def __init__(self, delay: float):
self.delay = delay
class ConnectionCommand(Command):
"""
Commands involving a specific connection
"""
connection: Connection
def __init__(self, connection: Connection):
self.connection = connection
class SendData(ConnectionCommand):
"""
Send data to a remote peer
"""
data: bytes
def __init__(self, connection: Connection, data: bytes):
super().__init__(connection)
self.data = data
def __repr__(self):
target = str(self.connection).split("(", 1)[0].lower()
return f"SendData({target}, {self.data!r})"
class OpenConnection(ConnectionCommand):
"""
Open a new connection
"""
connection: Server
blocking = True
class CloseConnection(ConnectionCommand):
"""
Close a connection. If the client connection is closed,
all other connections will ultimately be closed during cleanup.
"""
class CloseTcpConnection(CloseConnection):
half_close: bool
"""
If True, only close our half of the connection by sending a FIN packet.
This is required from some protocols which close their end to signal completion and then continue reading,
for example HTTP/1.0 without Content-Length header.
"""
def __init__(self, connection: Connection, half_close: bool = False):
super().__init__(connection)
self.half_close = half_close
class StartHook(Command, mitmproxy.hooks.Hook):
"""
Start an event hook in the mitmproxy core.
This triggers a particular function (derived from the class name) in all addons.
"""
name = ""
blocking = True
def __new__(cls, *args, **kwargs):
if cls is StartHook:
raise TypeError("StartHook may not be instantiated directly.")
return super().__new__(cls, *args, **kwargs)
class Log(Command):
"""
Log a message.
Layers could technically call `logging.log` directly, but the use of a command allows us to
write more expressive playbook tests. Put differently, by using commands we can assert that
a specific log message is a direct consequence of a particular I/O event.
This could also be implemented with some more playbook magic in the future,
but for now we keep the current approach as the fully sans-io one.
"""
message: str
level: int
def __init__(
self,
message: str,
level: int = logging.INFO,
):
if isinstance(level, str): # pragma: no cover
warnings.warn(
"commands.Log() now expects an integer log level, not a string.",
DeprecationWarning,
stacklevel=2,
)
level = getattr(logging, level.upper())
self.message = message
self.level = level
def __repr__(self):
return f"Log({self.message!r}, {logging.getLevelName(self.level).lower()})"