def patched_receive_handshake_data( self, data ) -> layer.CommandGenerator[typing.Tuple[bool, typing.Optional[str]]]: self.buf += data response_head = self.buf.maybe_extract_lines() if response_head: response_head = [bytes(x) for x in response_head] try: response = http1.read_response_head(response_head) except ValueError: return True, None challenge_message = extract_proxy_authenticate_msg( response_head) if 200 <= response.status_code < 300: if self.buf: yield from self.receive_data(data) del self.buf return True, None else: if not challenge_message: return True, None proxy_authorization = self.ntlm_context.get_ntlm_challenge_response_message( challenge_message) self.flow = build_connect_flow( self.context, ("Proxy-Authorization", proxy_authorization)) raw = http1.assemble_request(self.flow.request) yield commands.SendData(self.tunnel_connection, raw) return False, None else: return False, None
def receive_handshake_data( self, data: bytes) -> layer.CommandGenerator[Tuple[bool, Optional[str]]]: if not self.send_connect: return (yield from super().receive_handshake_data(data)) self.buf += data response_head = self.buf.maybe_extract_lines() if response_head: response_head = [ bytes(x) for x in response_head ] # TODO: Make url.parse compatible with bytearrays try: response = http1.read_response_head(response_head) except ValueError as e: yield commands.Log( f"{human.format_address(self.tunnel_connection.address)}: {e}" ) return False, str(e) if 200 <= response.status_code < 300: if self.buf: yield from self.receive_data(bytes(self.buf)) del self.buf return True, None else: raw_resp = b"\n".join(response_head) yield commands.Log( f"{human.format_address(self.tunnel_connection.address)}: {raw_resp!r}", level="debug") return False, f"{response.status_code} {response.reason}" else: return False, None
def read_headers( self, event: events.ConnectionEvent) -> layer.CommandGenerator[None]: if isinstance(event, events.DataReceived): if not self.request: # we just received some data for an unknown request. yield commands.Log( f"Unexpected data from server: {bytes(self.buf)!r}") yield commands.CloseConnection(self.conn) return assert self.stream_id response_head = self.buf.maybe_extract_lines() if response_head: response_head = [ bytes(x) for x in response_head ] # TODO: Make url.parse compatible with bytearrays try: self.response = http1.read_response_head(response_head) if self.context.options.validate_inbound_headers: http1.validate_headers(self.response.headers) expected_size = http1.expected_http_body_size( self.request, self.response) except ValueError as e: yield commands.CloseConnection(self.conn) yield ReceiveHttp( ResponseProtocolError( self.stream_id, f"Cannot parse HTTP response: {e}")) return yield ReceiveHttp( ResponseHeaders(self.stream_id, self.response, expected_size == 0)) self.body_reader = make_body_reader(expected_size) self.state = self.read_body yield from self.state(event) else: pass # FIXME: protect against header size DoS elif isinstance(event, events.ConnectionClosed): if self.conn.state & ConnectionState.CAN_WRITE: yield commands.CloseConnection(self.conn) if self.stream_id: if self.buf: yield ReceiveHttp( ResponseProtocolError( self.stream_id, f"unexpected server response: {bytes(self.buf)!r}") ) else: # The server has closed the connection to prevent us from continuing. # We need to signal that to the stream. # https://tools.ietf.org/html/rfc7231#section-6.5.11 yield ReceiveHttp( ResponseProtocolError(self.stream_id, "server closed connection")) else: return else: raise AssertionError(f"Unexpected event: {event}")
def test_stream_chunked(self): connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) connection.connect(("127.0.0.1", self.proxy.port)) fconn = connection.makefile("rb") spec = '200:h"Transfer-Encoding"="chunked":r:b"4\\r\\nthis\\r\\n11\\r\\nisatest__reachhex\\r\\n0\\r\\n\\r\\n"' connection.send(b"GET %s/p/%s HTTP/1.1\r\n" % (self.server.urlbase.encode(), spec.encode())) connection.send(b"\r\n") resp = http1.read_response_head(fconn) assert resp.headers["Transfer-Encoding"] == 'chunked' assert resp.status_code == 200 chunks = list(http1.read_body(fconn, None)) assert chunks == [b"this", b"isatest__reachhex"] connection.close()
def test_stream_chunked(self): connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM) connection.connect(("127.0.0.1", self.proxy.port)) fconn = connection.makefile("rb") spec = '200:h"Transfer-Encoding"="chunked":r:b"4\\r\\nthis\\r\\n11\\r\\nisatest__reachhex\\r\\n0\\r\\n\\r\\n"' connection.send( b"GET %s/p/%s HTTP/1.1\r\n" % (self.server.urlbase.encode(), spec.encode())) connection.send(b"\r\n") resp = http1.read_response_head(fconn) assert resp.headers["Transfer-Encoding"] == 'chunked' assert resp.status_code == 200 chunks = list(http1.read_body(fconn, None)) assert chunks == [b"this", b"isatest__reachhex"] connection.close()
def read_response_headers(self): resp = http1.read_response_head(self.server_conn.rfile) return http.HTTPResponse.wrap(resp)
def read_response_headers(self): return http1.read_response_head(self.server_conn.rfile)
def read_response_headers(self): resp = http1.read_response_head(self.server_conn.rfile) return http.HTTPResponse.wrap(resp)