コード例 #1
0
ファイル: _http1.py プロジェクト: vevenlcf/mitmproxy-1
    def read_body(self, event: events.Event) -> layer.CommandGenerator[None]:
        assert self.stream_id
        while True:
            try:
                if isinstance(event, events.DataReceived):
                    h11_event = self.body_reader(self.buf)
                elif isinstance(event, events.ConnectionClosed):
                    h11_event = self.body_reader.read_eof()
                else:
                    raise AssertionError(f"Unexpected event: {event}")
            except h11.ProtocolError as e:
                yield commands.CloseConnection(self.conn)
                yield ReceiveHttp(
                    self.ReceiveProtocolError(self.stream_id,
                                              f"HTTP/1 protocol error: {e}"))
                return

            if h11_event is None:
                return
            elif isinstance(h11_event, h11.Data):
                data: bytes = bytes(h11_event.data)
                if data:
                    yield ReceiveHttp(self.ReceiveData(self.stream_id, data))
            elif isinstance(h11_event, h11.EndOfMessage):
                assert self.request
                if h11_event.headers:
                    raise NotImplementedError(
                        f"HTTP trailers are not implemented yet.")
                if self.request.data.method.upper() != b"CONNECT":
                    yield ReceiveHttp(self.ReceiveEndOfMessage(self.stream_id))
                is_request = isinstance(self, Http1Server)
                yield from self.mark_done(request=is_request,
                                          response=not is_request)
                return
コード例 #2
0
    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}")
コード例 #3
0
ファイル: _http1.py プロジェクト: vevenlcf/mitmproxy-1
 def passthrough(self, event: events.Event) -> layer.CommandGenerator[None]:
     assert self.stream_id
     if isinstance(event, events.DataReceived):
         yield ReceiveHttp(self.ReceiveData(self.stream_id, event.data))
     elif isinstance(event, events.ConnectionClosed):
         if isinstance(self, Http1Server):
             yield ReceiveHttp(RequestEndOfMessage(self.stream_id))
         else:
             yield ReceiveHttp(ResponseEndOfMessage(self.stream_id))
コード例 #4
0
 def read_headers(
         self,
         event: events.ConnectionEvent) -> layer.CommandGenerator[None]:
     if isinstance(event, events.DataReceived):
         request_head = self.buf.maybe_extract_lines()
         if request_head:
             request_head = [
                 bytes(x) for x in request_head
             ]  # TODO: Make url.parse compatible with bytearrays
             try:
                 self.request = http1.read_request_head(request_head)
                 if self.context.options.validate_inbound_headers:
                     http1.validate_headers(self.request.headers)
                 expected_body_size = http1.expected_http_body_size(
                     self.request)
             except ValueError as e:
                 yield commands.SendData(self.conn,
                                         make_error_response(400, str(e)))
                 yield commands.CloseConnection(self.conn)
                 if self.request:
                     # we have headers that we can show in the ui
                     yield ReceiveHttp(
                         RequestHeaders(self.stream_id, self.request,
                                        False))
                     yield ReceiveHttp(
                         RequestProtocolError(self.stream_id, str(e), 400))
                 else:
                     yield commands.Log(
                         f"{human.format_address(self.conn.peername)}: {e}")
                 self.state = self.done
                 return
             yield ReceiveHttp(
                 RequestHeaders(self.stream_id, self.request,
                                expected_body_size == 0))
             self.body_reader = make_body_reader(expected_body_size)
             self.state = self.read_body
             yield from self.state(event)
         else:
             pass  # FIXME: protect against header size DoS
     elif isinstance(event, events.ConnectionClosed):
         buf = bytes(self.buf)
         if buf.strip():
             yield commands.Log(
                 f"Client closed connection before completing request headers: {buf!r}"
             )
         yield commands.CloseConnection(self.conn)
     else:
         raise AssertionError(f"Unexpected event: {event}")
コード例 #5
0
ファイル: _http1.py プロジェクト: weiplanet/mitmproxy
 def read_headers(self, event: events.ConnectionEvent) -> layer.CommandGenerator[None]:
     if isinstance(event, events.DataReceived):
         request_head = self.buf.maybe_extract_lines()
         if request_head:
             request_head = [bytes(x) for x in request_head]  # TODO: Make url.parse compatible with bytearrays
             try:
                 self.request = http1.read_request_head(request_head)
                 expected_body_size = http1.expected_http_body_size(self.request, expect_continue_as_0=False)
             except ValueError as e:
                 yield commands.Log(f"{human.format_address(self.conn.peername)}: {e}")
                 yield commands.CloseConnection(self.conn)
                 self.state = self.done
                 return
             yield ReceiveHttp(RequestHeaders(self.stream_id, self.request, expected_body_size == 0))
             self.body_reader = make_body_reader(expected_body_size)
             self.state = self.read_body
             yield from self.state(event)
         else:
             pass  # FIXME: protect against header size DoS
     elif isinstance(event, events.ConnectionClosed):
         buf = bytes(self.buf)
         if buf.strip():
             yield commands.Log(f"Client closed connection before completing request headers: {buf!r}")
         yield commands.CloseConnection(self.conn)
     else:
         raise AssertionError(f"Unexpected event: {event}")
コード例 #6
0
ファイル: _http1.py プロジェクト: weiplanet/mitmproxy
 def wait(self, event: events.Event) -> layer.CommandGenerator[None]:
     """
     We wait for the current flow to be finished before parsing the next message,
     as we may want to upgrade to WebSocket or plain TCP before that.
     """
     assert self.stream_id
     if isinstance(event, events.DataReceived):
         return
     elif isinstance(event, events.ConnectionClosed):
         # for practical purposes, we assume that a peer which sent at least a FIN
         # is not interested in any more data from us, see
         # see https://github.com/httpwg/http-core/issues/22
         if event.connection.state is not ConnectionState.CLOSED:
             yield commands.CloseConnection(event.connection)
         yield ReceiveHttp(self.ReceiveProtocolError(self.stream_id, f"Client disconnected.",
                                                     code=status_codes.CLIENT_CLOSED_REQUEST))
     else:  # pragma: no cover
         raise AssertionError(f"Unexpected event: {event}")