| 83 | |
| 84 | |
| 85 | class ReplayHandler(server.ConnectionHandler): |
| 86 | layer: layers.HttpLayer |
| 87 | |
| 88 | def __init__(self, flow: http.HTTPFlow, options: Options) -> None: |
| 89 | client = flow.client_conn.copy() |
| 90 | client.state = ConnectionState.OPEN |
| 91 | |
| 92 | context = Context(client, options) |
| 93 | context.server = Server(address=(flow.request.host, flow.request.port)) |
| 94 | if flow.request.scheme == "https": |
| 95 | context.server.tls = True |
| 96 | context.server.sni = flow.request.pretty_host |
| 97 | if options.mode and options.mode[0].startswith("upstream:"): |
| 98 | mode = UpstreamMode.parse(options.mode[0]) |
| 99 | assert isinstance(mode, UpstreamMode) # remove once mypy supports Self. |
| 100 | context.server.via = flow.server_conn.via = (mode.scheme, mode.address) |
| 101 | |
| 102 | super().__init__(context) |
| 103 | |
| 104 | if options.mode and options.mode[0].startswith("upstream:"): |
| 105 | self.layer = layers.HttpLayer(context, HTTPMode.upstream) |
| 106 | else: |
| 107 | self.layer = layers.HttpLayer(context, HTTPMode.transparent) |
| 108 | self.layer.connections[client] = MockServer(flow, context.fork()) |
| 109 | self.flow = flow |
| 110 | self.done = asyncio.Event() |
| 111 | |
| 112 | async def replay(self) -> None: |
| 113 | await self.server_event(events.Start()) |
| 114 | await self.done.wait() |
| 115 | |
| 116 | def log( |
| 117 | self, |
| 118 | message: str, |
| 119 | level: int = logging.INFO, |
| 120 | exc_info: Literal[True] |
| 121 | | tuple[type[BaseException] | None, BaseException | None, TracebackType | None] |
| 122 | | None = None, |
| 123 | ) -> None: |
| 124 | assert isinstance(level, int) |
| 125 | logger.log(level=level, msg=f"[replay] {message}") |
| 126 | |
| 127 | async def handle_hook(self, hook: commands.StartHook) -> None: |
| 128 | (data,) = hook.args() |
| 129 | await ctx.master.addons.handle_lifecycle(hook) |
| 130 | if isinstance(data, flow.Flow): |
| 131 | await data.wait_for_resume() |
| 132 | if isinstance(hook, (layers.http.HttpResponseHook, layers.http.HttpErrorHook)): |
| 133 | if self.transports: |
| 134 | # close server connections |
| 135 | for x in self.transports.values(): |
| 136 | if x.handler: |
| 137 | x.handler.cancel() |
| 138 | await asyncio.wait( |
| 139 | [x.handler for x in self.transports.values() if x.handler] |
| 140 | ) |
| 141 | # signal completion |
| 142 | self.done.set() |
no outgoing calls
no test coverage detected
searching dependent graphs…