def send_response(self, already_streamed: bool = False): """We have either consumed the entire response from the server or the response was set by an addon.""" assert self.flow.response self.flow.response.timestamp_end = time.time() yield HttpResponseHook(self.flow) self.server_state = self.state_done if (yield from self.check_killed(False)): return if not already_streamed: content = self.flow.response.raw_content yield SendHttp(ResponseHeaders(self.stream_id, self.flow.response, not content), self.context.client) if content: yield SendHttp(ResponseData(self.stream_id, content), self.context.client) yield SendHttp(ResponseEndOfMessage(self.stream_id), self.context.client) if self.flow.response.status_code == 101: is_websocket = ( self.flow.response.headers.get("upgrade", "").lower() == "websocket" and self.flow.request.headers.get("Sec-WebSocket-Version", "") == "13" ) if is_websocket: self.child_layer = websocket.WebsocketLayer(self.context, self.flow) else: self.child_layer = tcp.TCPLayer(self.context) if self.debug: yield commands.Log(f"{self.debug}[http] upgrading to {self.child_layer}", "debug") yield from self.child_layer.handle_event(events.Start()) self._handle_event = self.passthrough return
def send_response(self, already_streamed: bool = False): """We have either consumed the entire response from the server or the response was set by an addon.""" assert self.flow.response self.flow.response.timestamp_end = time.time() is_websocket = (self.flow.response.status_code == 101 and self.flow.response.headers.get( "upgrade", "").lower() == "websocket" and self.flow.request.headers.get( "Sec-WebSocket-Version", "").encode() == wsproto.handshake.WEBSOCKET_VERSION and self.context.options.websocket) if is_websocket: # We need to set this before calling the response hook # so that addons can determine if a WebSocket connection is following up. self.flow.websocket = WebSocketData() yield HttpResponseHook(self.flow) self.server_state = self.state_done if (yield from self.check_killed(False)): return if not already_streamed: content = self.flow.response.raw_content done_after_headers = not (content or self.flow.response.trailers) yield SendHttp( ResponseHeaders(self.stream_id, self.flow.response, done_after_headers), self.context.client) if content: yield SendHttp(ResponseData(self.stream_id, content), self.context.client) if self.flow.response.trailers: yield SendHttp( ResponseTrailers(self.stream_id, self.flow.response.trailers), self.context.client) yield SendHttp(ResponseEndOfMessage(self.stream_id), self.context.client) if self.flow.response.status_code == 101: if is_websocket: self.child_layer = websocket.WebsocketLayer( self.context, self.flow) elif self.context.options.rawtcp: self.child_layer = tcp.TCPLayer(self.context) else: yield commands.Log( f"Sent HTTP 101 response, but no protocol is enabled to upgrade to.", "warn") yield commands.CloseConnection(self.context.client) self.client_state = self.server_state = self.state_errored return if self.debug: yield commands.Log( f"{self.debug}[http] upgrading to {self.child_layer}", "debug") yield from self.child_layer.handle_event(events.Start()) self._handle_event = self.passthrough return
def ws_testdata(tctx): tctx.server.address = ("example.com", 80) tctx.server.state = ConnectionState.OPEN flow = HTTPFlow(tctx.client, tctx.server) flow.request = Request.make("GET", "http://example.com/", headers={ "Connection": "upgrade", "Upgrade": "websocket", "Sec-WebSocket-Version": "13", }) flow.response = Response.make(101, headers={ "Connection": "upgrade", "Upgrade": "websocket", }) return tctx, Playbook(websocket.WebsocketLayer(tctx, flow))