Пример #1
0
def _read_request_line(
        line: bytes) -> Tuple[str, int, bytes, bytes, bytes, bytes, bytes]:
    try:
        method, target, http_version = line.split()
        port: Optional[int]

        if target == b"*" or target.startswith(b"/"):
            scheme, authority, path = b"", b"", target
            host, port = "", 0
        elif method == b"CONNECT":
            scheme, authority, path = b"", target, b""
            host, port = url.parse_authority(authority, check=True)
            if not port:
                raise ValueError
        else:
            scheme, rest = target.split(b"://", maxsplit=1)
            authority, path_ = rest.split(b"/", maxsplit=1)
            path = b"/" + path_
            host, port = url.parse_authority(authority, check=True)
            port = port or url.default_port(scheme)
            if not port:
                raise ValueError
            # TODO: we can probably get rid of this check?
            url.parse(target)

        raise_if_http_version_unknown(http_version)
    except ValueError as e:
        raise ValueError(f"Bad HTTP request line: {line!r}") from e

    return host, port, method, scheme, authority, path, http_version
Пример #2
0
    def read_request_headers(self, flow):
        self.request_message.arrived.wait()
        self.raise_zombie()

        if self.pushed:
            flow.metadata['h2-pushed-stream'] = True

        # pseudo header must be present, see https://http2.github.io/http2-spec/#rfc.section.8.1.2.3
        authority = self.request_message.headers.pop(':authority', "")
        method = self.request_message.headers.pop(':method')
        scheme = self.request_message.headers.pop(':scheme')
        path = self.request_message.headers.pop(':path')

        host, port = url.parse_authority(authority, check=True)
        port = port or url.default_port(scheme) or 0

        return http.HTTPRequest(
            host,
            port,
            method.encode(),
            scheme.encode(),
            authority.encode(),
            path.encode(),
            b"HTTP/2.0",
            self.request_message.headers,
            None,
            None,
            self.timestamp_start,
            self.timestamp_end,
        )
Пример #3
0
def _read_request_line(rfile):
    try:
        line = _get_first_line(rfile)
    except exceptions.HttpReadDisconnect:
        # We want to provide a better error message.
        raise exceptions.HttpReadDisconnect("Client disconnected")

    try:
        method, target, http_version = line.split()

        if target == b"*" or target.startswith(b"/"):
            scheme, authority, path = b"", b"", target
            host, port = "", 0
        elif method == b"CONNECT":
            scheme, authority, path = b"", target, b""
            host, port = url.parse_authority(authority, check=True)
            if not port:
                raise ValueError
        else:
            scheme, rest = target.split(b"://", maxsplit=1)
            authority, path_ = rest.split(b"/", maxsplit=1)
            path = b"/" + path_
            host, port = url.parse_authority(authority, check=True)
            port = port or url.default_port(scheme)
            if not port:
                raise ValueError
            # TODO: we can probably get rid of this check?
            url.parse(target)

        _check_http_version(http_version)
    except ValueError:
        raise exceptions.HttpSyntaxException(f"Bad HTTP request line: {line}")

    return host, port, method, scheme, authority, path, http_version
    def read_request(
        self,
        __rfile,
        include_body=True,
        body_size_limit=None,
        allow_empty=False,
    ):
        if body_size_limit is not None:
            raise NotImplementedError()

        self.perform_connection_preface()

        timestamp_start = time.time()
        if hasattr(self.tcp_handler.rfile, "reset_timestamps"):
            self.tcp_handler.rfile.reset_timestamps()

        stream_id, headers, body = self._receive_transmission(
            include_body=include_body,
        )

        if hasattr(self.tcp_handler.rfile, "first_byte_timestamp"):
            # more accurate timestamp_start
            timestamp_start = self.tcp_handler.rfile.first_byte_timestamp

        timestamp_end = time.time()

        # pseudo header must be present, see https://http2.github.io/http2-spec/#rfc.section.8.1.2.3
        authority = headers.pop(':authority', "")
        method = headers.pop(':method', "")
        scheme = headers.pop(':scheme', "")
        path = headers.pop(':path', "")

        host, port = url.parse_authority(authority, check=False)
        port = port or url.default_port(scheme) or 0

        request = mitmproxy.net.http.Request(
            host=host,
            port=port,
            method=method.encode(),
            scheme=scheme.encode(),
            authority=authority.encode(),
            path=path.encode(),
            http_version=b"HTTP/2.0",
            headers=headers,
            content=body,
            trailers=None,
            timestamp_start=timestamp_start,
            timestamp_end=timestamp_end,
        )
        request.stream_id = stream_id

        return request
Пример #5
0
    def pretty_url(self) -> str:
        """
        Like :py:attr:`url`, but using :py:attr:`pretty_host` instead of :py:attr:`host`.
        """
        if self.first_line_format == "authority":
            return self.authority

        host_header = self.host_header
        if not host_header:
            return self.url

        pretty_host, pretty_port = url.parse_authority(host_header,
                                                       check=False)
        pretty_port = pretty_port or url.default_port(self.scheme) or 443

        return url.unparse(self.scheme, pretty_host, pretty_port, self.path)
Пример #6
0
def test_default_port():
    assert url.default_port("http") == 80
    assert url.default_port(b"https") == 443
    assert url.default_port(b"qux") is None