Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
master.py146 linesDownload Raw Back to mitmproxy
1import asyncio2import logging3 4from . import ctx as mitmproxy_ctx5from .addons import termlog6from .proxy.mode_specs import ReverseMode7from .utils import asyncio_utils8from mitmproxy import addonmanager9from mitmproxy import command10from mitmproxy import eventsequence11from mitmproxy import hooks12from mitmproxy import http13from mitmproxy import log14from mitmproxy import options15 16logger = logging.getLogger(__name__)17 18 19class Master:20    """21    The master handles mitmproxy's main event loop.22    """23 24    event_loop: asyncio.AbstractEventLoop25    _termlog_addon: termlog.TermLog | None = None26 27    def __init__(28        self,29        opts: options.Options | None,30        event_loop: asyncio.AbstractEventLoop | None = None,31        with_termlog: bool = False,32    ):33        self.options: options.Options = opts or options.Options()34        self.commands = command.CommandManager(self)35        self.addons = addonmanager.AddonManager(self)36 37        if with_termlog:38            self._termlog_addon = termlog.TermLog()39            self.addons.add(self._termlog_addon)40 41        self.log = log.Log(self)  # deprecated, do not use.42        self._legacy_log_events = log.LegacyLogEvents(self)43        self._legacy_log_events.install()44 45        # We expect an active event loop here already because some addons46        # may want to spawn tasks during the initial configuration phase,47        # which happens before run().48        self.event_loop = event_loop or asyncio.get_running_loop()49        self.should_exit = asyncio.Event()50        mitmproxy_ctx.master = self51        mitmproxy_ctx.log = self.log  # deprecated, do not use.52        mitmproxy_ctx.options = self.options53 54    async def run(self) -> None:55        with (56            asyncio_utils.install_exception_handler(self._asyncio_exception_handler),57            asyncio_utils.set_eager_task_factory(),58        ):59            self.should_exit.clear()60 61            # Can we exit before even bringing up servers?62            if ec := self.addons.get("errorcheck"):63                await ec.shutdown_if_errored()64            if ps := self.addons.get("proxyserver"):65                # This may block for some proxy modes, so we also monitor should_exit.66                await asyncio.wait(67                    [68                        asyncio_utils.create_task(69                            ps.setup_servers(), name="setup_servers", keep_ref=False70                        ),71                        asyncio_utils.create_task(72                            self.should_exit.wait(), name="should_exit", keep_ref=False73                        ),74                    ],75                    return_when=asyncio.FIRST_COMPLETED,76                )77                if self.should_exit.is_set():78                    return79                # Did bringing up servers fail?80                if ec := self.addons.get("errorcheck"):81                    await ec.shutdown_if_errored()82 83            try:84                await self.running()85                # Any errors in the final part of startup?86                if ec := self.addons.get("errorcheck"):87                    await ec.shutdown_if_errored()88                    ec.finish()89 90                await self.should_exit.wait()91            finally:92                # if running() was called, we also always want to call done().93                # .wait might be cancelled (e.g. by sys.exit), so  this needs to be in a finally block.94                await self.done()95 96    def shutdown(self):97        """98        Shut down the proxy. This method is thread-safe.99        """100        # We may add an exception argument here.101        self.event_loop.call_soon_threadsafe(self.should_exit.set)102 103    async def running(self) -> None:104        await self.addons.trigger_event(hooks.RunningHook())105 106    async def done(self) -> None:107        await self.addons.trigger_event(hooks.DoneHook())108        self._legacy_log_events.uninstall()109        if self._termlog_addon is not None:110            self._termlog_addon.uninstall()111 112    def _asyncio_exception_handler(self, loop, context) -> None:113        try:114            exc: Exception = context["exception"]115        except KeyError:116            logger.error(f"Unhandled asyncio error: {context}")117        else:118            if isinstance(exc, OSError) and exc.errno == 10038:119                return  # suppress https://bugs.python.org/issue43253120            logger.error(121                "Unhandled error in task.",122                exc_info=(type(exc), exc, exc.__traceback__),123            )124 125    async def load_flow(self, f):126        """127        Loads a flow128        """129 130        if (131            isinstance(f, http.HTTPFlow)132            and len(self.options.mode) == 1133            and self.options.mode[0].startswith("reverse:")134        ):135            # When we load flows in reverse proxy mode, we adjust the target host to136            # the reverse proxy destination for all flows we load. This makes it very137            # easy to replay saved flows against a different host.138            # We may change this in the future so that clientplayback always replays to the first mode.139            mode = ReverseMode.parse(self.options.mode[0])140            assert isinstance(mode, ReverseMode)141            f.request.host, f.request.port, *_ = mode.address142            f.request.scheme = mode.scheme143 144        for e in eventsequence.iterate(f):145            await self.addons.handle_lifecycle(e)146 
codekingpro/portable-devtools · Team Ai