diff options
author | Aldo Cortesi <aldo@nullcube.com> | 2012-06-09 21:27:43 +1200 |
---|---|---|
committer | Aldo Cortesi <aldo@nullcube.com> | 2012-06-09 21:27:43 +1200 |
commit | 9130cd63d36103055e6ec34bacca37e7532ef366 (patch) | |
tree | 175ee297d36c10819d01e52eca522d1abe94c04c | |
parent | 18c1b444759b38d1a2643c908bfd6cab0e016e69 (diff) | |
download | mitmproxy-9130cd63d36103055e6ec34bacca37e7532ef366.tar.gz mitmproxy-9130cd63d36103055e6ec34bacca37e7532ef366.tar.bz2 mitmproxy-9130cd63d36103055e6ec34bacca37e7532ef366.zip |
Significant cleanup of proxy internals.
Dispense with the loose parsing of client requests that we had before. We now
have service modes ("proxy" and "reverse proxy" for now), and we only accept
requests that are appropriate for the mode we're in.
-rw-r--r-- | libmproxy/proxy.py | 87 |
1 files changed, 41 insertions, 46 deletions
diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py index 2d4ee988..41f101d8 100644 --- a/libmproxy/proxy.py +++ b/libmproxy/proxy.py @@ -450,14 +450,43 @@ class ProxyHandler(SocketServer.StreamRequestHandler): self.rfile = FileLike(self.connection) self.wfile = FileLike(self.connection) + def read_contents(self, client_conn, headers, httpminor): + if "expect" in headers: + # FIXME: Should be forwarded upstream + expect = ",".join(headers['expect']) + if expect == "100-continue" and httpminor >= 1: + self.wfile.write('HTTP/1.1 100 Continue\r\n') + self.wfile.write('Proxy-agent: %s\r\n'%version.NAMEVERSION) + self.wfile.write('\r\n') + del headers['expect'] + else: + raise ProxyError(417, 'Unmet expect: %s'%expect) + if httpminor == 0: + client_conn.close = True + if "connection" in headers: + for value in ",".join(headers['connection']).split(","): + value = value.strip() + if value == "close": + client_conn.close = True + if value == "keep-alive": + client_conn.close = False + return read_http_body(self.rfile, client_conn, headers, False, self.config.body_size_limit) + def read_request(self, client_conn): line = self.rfile.readline() if line == "\r\n" or line == "\n": # Possible leftover from previous message line = self.rfile.readline() if line == "": return None - method, scheme, host, port, path, httpminor = parse_request_line(line) - if method == "CONNECT": + + if self.config.reverse_proxy: + scheme, host, port = self.config.reverse_proxy + method, path, httpmajor, httpminor = parse_init_http(line) + headers = read_headers(self.rfile) + content = self.read_contents(client_conn, headers, httpminor) + return flow.Request(client_conn, host, port, "http", method, path, headers, content) + elif line.startswith("CONNECT"): + host, port, httpmajor, httpminor = parse_init_connect(line) # FIXME: Discard additional headers sent to the proxy. Should I expose # these to users? while 1: @@ -472,50 +501,16 @@ class ProxyHandler(SocketServer.StreamRequestHandler): self.wfile.flush() certfile = self.find_cert(host, port) self.convert_to_ssl(certfile) - method, scheme, host, port, path, httpminor = parse_request_line(self.rfile.readline()) - if scheme is None: - scheme = "https" - headers = read_headers(self.rfile) - if host is None and "host" in headers: - netloc = headers["host"][0] - if ':' in netloc: - host, port = string.split(netloc, ':') - port = int(port) - else: - host = netloc - if scheme == "https": - port = 443 - else: - port = 80 - port = int(port) - if host is None: - if self.config.reverse_proxy: - scheme, host, port = self.config.reverse_proxy - else: - # FIXME: We only specify the first part of the invalid request in this error. - # We should gather up everything read from the socket, and specify it all. - raise ProxyError(400, 'Invalid request: %s'%line) - if "expect" in headers: - # FIXME: Should be forwarded upstream - expect = ",".join(headers['expect']) - if expect == "100-continue" and httpminor >= 1: - self.wfile.write('HTTP/1.1 100 Continue\r\n') - self.wfile.write('Proxy-agent: %s\r\n'%version.NAMEVERSION) - self.wfile.write('\r\n') - del headers['expect'] - else: - raise ProxyError(417, 'Unmet expect: %s'%expect) - if httpminor == 0: - client_conn.close = True - if "connection" in headers: - for value in ",".join(headers['connection']).split(","): - value = value.strip() - if value == "close": - client_conn.close = True - if value == "keep-alive": - client_conn.close = False - content = read_http_body(self.rfile, client_conn, headers, False, self.config.body_size_limit) - return flow.Request(client_conn, host, port, scheme, method, path, headers, content) + + method, path, httpmajor, httpminor = parse_init_http(self.rfile.readline(line)) + headers = read_headers(self.rfile) + content = self.read_contents(client_conn, headers, httpminor) + return flow.Request(client_conn, host, port, "https", method, path, headers, content) + else: + method, scheme, host, port, path, httpmajor, httpminor = parse_init_proxy(line) + headers = read_headers(self.rfile) + content = self.read_contents(client_conn, headers, httpminor) + return flow.Request(client_conn, host, port, scheme, method, path, headers, content) def send_response(self, response): d = response._assemble() |