Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_upstream_proxy.py106 linesDownload Raw Back to http
1import time2from logging import DEBUG3 4from h11._receivebuffer import ReceiveBuffer5 6from mitmproxy import connection7from mitmproxy import http8from mitmproxy.net.http import http19from mitmproxy.proxy import commands10from mitmproxy.proxy import context11from mitmproxy.proxy import layer12from mitmproxy.proxy import tunnel13from mitmproxy.proxy.layers import tls14from mitmproxy.proxy.layers.http._hooks import HttpConnectUpstreamHook15from mitmproxy.utils import human16 17 18class HttpUpstreamProxy(tunnel.TunnelLayer):19    buf: ReceiveBuffer20    send_connect: bool21    conn: connection.Server22    tunnel_connection: connection.Server23 24    def __init__(25        self, ctx: context.Context, tunnel_conn: connection.Server, send_connect: bool26    ):27        super().__init__(ctx, tunnel_connection=tunnel_conn, conn=ctx.server)28        self.buf = ReceiveBuffer()29        self.send_connect = send_connect30 31    @classmethod32    def make(cls, ctx: context.Context, send_connect: bool) -> tunnel.LayerStack:33        assert ctx.server.via34        scheme, address = ctx.server.via35        assert scheme in ("http", "https")36 37        http_proxy = connection.Server(address=address)38 39        stack = tunnel.LayerStack()40        if scheme == "https":41            http_proxy.alpn_offers = tls.HTTP1_ALPNS42            http_proxy.sni = address[0]43            stack /= tls.ServerTLSLayer(ctx, http_proxy)44        stack /= cls(ctx, http_proxy, send_connect)45 46        return stack47 48    def start_handshake(self) -> layer.CommandGenerator[None]:49        if not self.send_connect:50            return (yield from super().start_handshake())51        assert self.conn.address52        flow = http.HTTPFlow(self.context.client, self.tunnel_connection)53        authority = (54            self.conn.address[0].encode("idna") + f":{self.conn.address[1]}".encode()55        )56        headers = http.Headers()57        if self.context.options.http_connect_send_host_header:58            headers.insert(0, b"Host", authority)59        flow.request = http.Request(60            host=self.conn.address[0],61            port=self.conn.address[1],62            method=b"CONNECT",63            scheme=b"",64            authority=authority,65            path=b"",66            http_version=b"HTTP/1.1",67            headers=headers,68            content=b"",69            trailers=None,70            timestamp_start=time.time(),71            timestamp_end=time.time(),72        )73        yield HttpConnectUpstreamHook(flow)74        raw = http1.assemble_request(flow.request)75        yield commands.SendData(self.tunnel_connection, raw)76 77    def receive_handshake_data(78        self, data: bytes79    ) -> layer.CommandGenerator[tuple[bool, str | None]]:80        if not self.send_connect:81            return (yield from super().receive_handshake_data(data))82        self.buf += data83        response_head = self.buf.maybe_extract_lines()84        if response_head:85            try:86                response = http1.read_response_head([bytes(x) for x in response_head])87            except ValueError as e:88                proxyaddr = human.format_address(self.tunnel_connection.address)89                yield commands.Log(f"{proxyaddr}: {e}")90                return False, f"Error connecting to {proxyaddr}: {e}"91            if 200 <= response.status_code < 300:92                if self.buf:93                    yield from self.receive_data(bytes(self.buf))94                    del self.buf95                return True, None96            else:97                proxyaddr = human.format_address(self.tunnel_connection.address)98                raw_resp = b"\n".join(response_head)99                yield commands.Log(f"{proxyaddr}: {raw_resp!r}", DEBUG)100                return (101                    False,102                    f"Upstream proxy {proxyaddr} refused HTTP CONNECT request: {response.status_code} {response.reason}",103                )104        else:105            return False, None106 
codekingpro/portable-devtools · Team Ai