aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Kriechbaumer <thomas@kriechbaumer.name>2015-08-01 14:36:31 +0200
committerThomas Kriechbaumer <thomas@kriechbaumer.name>2015-08-01 14:37:33 +0200
commitb732a1cb3d1a31e0827de60092badfe162e920a3 (patch)
treed2ab3de25a14f7bb3311b4a4a314071af54ce0c1
parent54866c0faa73f9c2dd34712ddc0a5f7e4d16f0db (diff)
downloadmitmproxy-b732a1cb3d1a31e0827de60092badfe162e920a3.tar.gz
mitmproxy-b732a1cb3d1a31e0827de60092badfe162e920a3.tar.bz2
mitmproxy-b732a1cb3d1a31e0827de60092badfe162e920a3.zip
reimplement streaming for HTTP/1
-rw-r--r--libmproxy/flow.py3
-rw-r--r--libmproxy/protocol/http.py109
-rw-r--r--libmproxy/proxy/server.py6
3 files changed, 59 insertions, 59 deletions
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index 82a25461..3d9ef722 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -844,8 +844,7 @@ class FlowMaster(controller.Master):
host,
port,
path,
- (1,
- 1),
+ (1, 1),
headers,
None,
None,
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py
index b54d4a11..a85a4f30 100644
--- a/libmproxy/protocol/http.py
+++ b/libmproxy/protocol/http.py
@@ -176,10 +176,10 @@ class HTTPHandler(ProtocolHandler):
# Only get the headers at first...
flow.response = HTTPResponse.from_protocol(
- flow.server_conn.protocol,
+ self.c.server_conn.protocol,
flow.request.method,
body_size_limit=self.c.config.body_size_limit,
- include_body=False
+ include_body=False,
)
break
except (tcp.NetLibError, http.HttpErrorConnClosed) as v:
@@ -214,9 +214,9 @@ class HTTPHandler(ProtocolHandler):
if flow.response.stream:
flow.response.content = CONTENT_MISSING
else:
- if isinstance(flow.server_conn.protocol, http1.HTTP1Protocol):
+ if isinstance(self.c.server_conn.protocol, http1.HTTP1Protocol):
# streaming is only supported with HTTP/1 at the moment
- flow.response.content = flow.server_conn.protocol.read_http_body(
+ flow.response.content = self.c.server_conn.protocol.read_http_body(
flow.response.headers,
self.c.config.body_size_limit,
flow.request.method,
@@ -369,43 +369,42 @@ class HTTPHandler(ProtocolHandler):
flow.error = Error(message or message_debug)
self.c.channel.ask("error", flow)
try:
- code = getattr(error, "code", 502)
+ status_code = getattr(error, "code", 502)
headers = getattr(error, "headers", None)
html_message = message or ""
if message_debug:
html_message += "<pre>%s</pre>" % message_debug
- self.send_error(code, html_message, headers)
+ self.send_error(status_code, html_message, headers)
except:
pass
- def send_error(self, code, message, headers):
- # TODO: implement this again
- raise NotImplementedError("todo - adapt for HTTP/2 - make use of make_error_reponse from pathod")
- # response = http.status_codes.RESPONSES.get(code, "Unknown")
- # html_content = """
- # <html>
- # <head>
- # <title>%d %s</title>
- # </head>
- # <body>%s</body>
- # </html>
- # """ % (code, response, message)
- # self.c.client_conn.wfile.write("HTTP/1.1 %s %s\r\n" % (code, response))
- # self.c.client_conn.wfile.write(
- # "Server: %s\r\n" % self.c.config.server_version
- # )
- # self.c.client_conn.wfile.write("Content-type: text/html\r\n")
- # self.c.client_conn.wfile.write(
- # "Content-Length: %d\r\n" % len(html_content)
- # )
- # if headers:
- # for key, value in headers.items():
- # self.c.client_conn.wfile.write("%s: %s\r\n" % (key, value))
- # self.c.client_conn.wfile.write("Connection: close\r\n")
- # self.c.client_conn.wfile.write("\r\n")
- # self.c.client_conn.wfile.write(html_content)
- # self.c.client_conn.wfile.flush()
+ def send_error(self, status_code, message, headers):
+ response = http.status_codes.RESPONSES.get(status_code, "Unknown")
+ body = """
+ <html>
+ <head>
+ <title>%d %s</title>
+ </head>
+ <body>%s</body>
+ </html>
+ """ % (status_code, response, message)
+
+ if not headers:
+ headers = odict.ODictCaseless()
+ headers["Server"] = [self.c.config.server_version]
+ headers["Connection"] = ["close"]
+ headers["Content-Length"] = [len(body)]
+ headers["Content-Type"] = ["text/html"]
+
+ resp = HTTPResponse(
+ (1, 1),
+ status_code,
+ '',
+ headers,
+ body,
+ )
+ self.c.client_conn.send(self.c.client_conn.protocol.assemble(resp))
def process_request(self, flow, request):
"""
@@ -566,31 +565,33 @@ class HTTPHandler(ProtocolHandler):
# send it to the client straight away.
self.c.client_conn.send(self.c.client_conn.protocol.assemble(flow.response))
else:
- raise NotImplementedError("HTTP streaming is currently not supported.")
- # TODO: implement it according to new protocols and messages
+ if isinstance(self.c.client_conn.protocol, http2.HTTP2Protocol):
+ raise NotImplementedError("HTTP streaming with HTTP/2 is currently not supported.")
+
# streaming:
# First send the headers and then transfer the response
# incrementally:
- # h = flow.response._assemble_head(preserve_transfer_encoding=True)
- # self.c.client_conn.send(h)
- #
- # protocol = http1.HTTP1Protocol(rfile=self.c.server_conn.rfile)
- # chunks = protocol.read_http_body_chunked(
- # flow.response.headers,
- # self.c.config.body_size_limit,
- # flow.request.method,
- # flow.response.code,
- # False,
- # 4096
- # )
- # if callable(flow.response.stream):
- # chunks = flow.response.stream(chunks)
- # for chunk in chunks:
- # for part in chunk:
- # self.c.client_conn.wfile.write(part)
- # self.c.client_conn.wfile.flush()
- # flow.response.timestamp_end = utils.timestamp()
+ h = self.c.client_conn.protocol._assemble_response_first_line(flow.response)
+ self.c.client_conn.send(h + "\r\n")
+ h = self.c.client_conn.protocol._assemble_response_headers(flow.response, preserve_transfer_encoding=True)
+ self.c.client_conn.send(h + "\r\n\r\n")
+
+ chunks = self.c.server_conn.protocol.read_http_body_chunked(
+ flow.response.headers,
+ self.c.config.body_size_limit,
+ flow.request.method,
+ flow.response.code,
+ False,
+ 4096
+ )
+ if callable(flow.response.stream):
+ chunks = flow.response.stream(chunks)
+ for chunk in chunks:
+ for part in chunk:
+ self.c.client_conn.wfile.write(part)
+ self.c.client_conn.wfile.flush()
+ flow.response.timestamp_end = utils.timestamp()
def check_close_connection(self, flow):
"""
diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py
index e77439fb..2f6ee061 100644
--- a/libmproxy/proxy/server.py
+++ b/libmproxy/proxy/server.py
@@ -117,7 +117,7 @@ class ConnectionHandler:
self.server_conn.address(),
"info")
self.conntype = "tcp"
-
+
elif not self.server_conn and self.config.mode == "sslspoof":
port = self.config.mode.sslport
self.set_server_address(("-", port))
@@ -243,7 +243,7 @@ class ConnectionHandler:
ssl_cert_err = self.server_conn.ssl_verification_error
if ssl_cert_err is not None:
self.log(
- "SSL verification failed for upstream server at depth %s with error: %s" %
+ "SSL verification failed for upstream server at depth %s with error: %s" %
(ssl_cert_err['depth'], ssl_cert_err['errno']),
"error")
self.log("Ignoring server verification error, continuing with connection", "error")
@@ -259,7 +259,7 @@ class ConnectionHandler:
ssl_cert_err = self.server_conn.ssl_verification_error
if ssl_cert_err is not None:
self.log(
- "SSL verification failed for upstream server at depth %s with error: %s" %
+ "SSL verification failed for upstream server at depth %s with error: %s" %
(ssl_cert_err['depth'], ssl_cert_err['errno']),
"error")
self.log("Aborting connection attempt", "error")