(self, event: events.Event)
| 949 | return f"HttpLayer({self.mode.name}, conns: {len(self.connections)})" |
| 950 | |
| 951 | def _handle_event(self, event: events.Event): |
| 952 | if isinstance(event, events.Start): |
| 953 | http_conn: HttpConnection |
| 954 | if is_h3_alpn(self.context.client.alpn): |
| 955 | http_conn = Http3Server(self.context.fork()) |
| 956 | elif self.context.client.alpn == b"h2": |
| 957 | http_conn = Http2Server(self.context.fork()) |
| 958 | else: |
| 959 | http_conn = Http1Server(self.context.fork()) |
| 960 | |
| 961 | # may have been set by client playback. |
| 962 | self.connections.setdefault(self.context.client, http_conn) |
| 963 | yield from self.event_to_child(self.connections[self.context.client], event) |
| 964 | if self.mode is HTTPMode.upstream: |
| 965 | proxy_mode = self.context.client.proxy_mode |
| 966 | assert isinstance(proxy_mode, UpstreamMode) |
| 967 | self.context.server.via = (proxy_mode.scheme, proxy_mode.address) |
| 968 | elif isinstance(event, events.CommandCompleted): |
| 969 | stream = self.command_sources.pop(event.command) |
| 970 | yield from self.event_to_child(stream, event) |
| 971 | elif isinstance(event, events.MessageInjected): |
| 972 | # For injected messages we pass the HTTP stacks entirely and directly address the stream. |
| 973 | try: |
| 974 | conn = self.connections[event.flow.server_conn] |
| 975 | except KeyError: |
| 976 | # We have a miss for the server connection, which means we're looking at a connection object |
| 977 | # that is tunneled over another connection (for example: over an upstream HTTP proxy). |
| 978 | # We now take the stream associated with the client connection. That won't work for HTTP/2, |
| 979 | # but it's good enough for HTTP/1. |
| 980 | conn = self.connections[event.flow.client_conn] |
| 981 | if isinstance(conn, HttpStream): |
| 982 | stream_id = conn.stream_id |
| 983 | else: |
| 984 | # We reach to the end of the connection's child stack to get the HTTP/1 client layer, |
| 985 | # which tells us which stream we are dealing with. |
| 986 | conn = conn.context.layers[-1] |
| 987 | assert isinstance(conn, Http1Connection) |
| 988 | assert conn.stream_id |
| 989 | stream_id = conn.stream_id |
| 990 | yield from self.event_to_child(self.streams[stream_id], event) |
| 991 | elif isinstance(event, events.ConnectionEvent): |
| 992 | if ( |
| 993 | event.connection == self.context.server |
| 994 | and self.context.server not in self.connections |
| 995 | ): |
| 996 | # We didn't do anything with this connection yet, now the peer is doing something. |
| 997 | if isinstance(event, events.ConnectionClosed): |
| 998 | # The peer has closed it - let's close it too! |
| 999 | yield commands.CloseConnection(event.connection) |
| 1000 | elif isinstance(event, (events.DataReceived, QuicStreamEvent)): |
| 1001 | # The peer has sent data or another connection activity occurred. |
| 1002 | # This can happen with HTTP/2 servers that already send a settings frame. |
| 1003 | child_layer: HttpConnection |
| 1004 | if is_h3_alpn(self.context.server.alpn): |
| 1005 | child_layer = Http3Client(self.context.fork()) |
| 1006 | elif self.context.server.alpn == b"h2": |
| 1007 | child_layer = Http2Client(self.context.fork()) |
| 1008 | else: |
nothing calls this directly
no test coverage detected