aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2012-06-09 21:27:43 +1200
committerAldo Cortesi <aldo@nullcube.com>2012-06-09 21:27:43 +1200
commit9130cd63d36103055e6ec34bacca37e7532ef366 (patch)
tree175ee297d36c10819d01e52eca522d1abe94c04c /libmproxy
parent18c1b444759b38d1a2643c908bfd6cab0e016e69 (diff)
downloadmitmproxy-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.
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/proxy.py87
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()