diff options
author | Aldo Cortesi <aldo@nullcube.com> | 2016-10-03 12:03:11 +1100 |
---|---|---|
committer | Aldo Cortesi <aldo@nullcube.com> | 2016-10-04 08:13:56 +1100 |
commit | 1ae73b915783350105897d1d875b7b1f2979ffe0 (patch) | |
tree | 933d81dc1e1a269b32f3d0c2e157bbddb6d09bba | |
parent | b73569465391e6f159c6690fc08a566a2c0bbafb (diff) | |
download | mitmproxy-1ae73b915783350105897d1d875b7b1f2979ffe0.tar.gz mitmproxy-1ae73b915783350105897d1d875b7b1f2979ffe0.tar.bz2 mitmproxy-1ae73b915783350105897d1d875b7b1f2979ffe0.zip |
Add requestheaders event
HTTP1 only for now, HTTP2 coming next.
-rw-r--r-- | mitmproxy/controller.py | 1 | ||||
-rw-r--r-- | mitmproxy/flow/master.py | 5 | ||||
-rw-r--r-- | mitmproxy/protocol/http.py | 34 | ||||
-rw-r--r-- | mitmproxy/protocol/http1.py | 7 | ||||
-rw-r--r-- | test/mitmproxy/builtins/test_script.py | 2 |
5 files changed, 32 insertions, 17 deletions
diff --git a/mitmproxy/controller.py b/mitmproxy/controller.py index ea084973..7996eb46 100644 --- a/mitmproxy/controller.py +++ b/mitmproxy/controller.py @@ -25,6 +25,7 @@ Events = frozenset([ "tcp_close", "request", + "requestheaders", "response", "responseheaders", diff --git a/mitmproxy/flow/master.py b/mitmproxy/flow/master.py index de9d47f1..7149fec9 100644 --- a/mitmproxy/flow/master.py +++ b/mitmproxy/flow/master.py @@ -18,6 +18,7 @@ from mitmproxy.protocol import http_replay def event_sequence(f): if isinstance(f, models.HTTPFlow): if f.request: + yield "requestheaders", f yield "request", f if f.response: yield "responseheaders", f @@ -216,6 +217,10 @@ class FlowMaster(controller.Master): self.state.update_flow(f) @controller.handler + def requestheaders(self, f): + pass + + @controller.handler def request(self, f): if f.live: app = self.apps.get(f.request) diff --git a/mitmproxy/protocol/http.py b/mitmproxy/protocol/http.py index 4a30edb7..744733a8 100644 --- a/mitmproxy/protocol/http.py +++ b/mitmproxy/protocol/http.py @@ -16,23 +16,23 @@ from netlib import websockets class _HttpTransmissionLayer(base.Layer): - - def read_request(self): + def read_request_headers(self): raise NotImplementedError() def read_request_body(self, request): raise NotImplementedError() + def read_request(self): + request = self.read_request_headers() + request.data.content = b"".join( + self.read_request_body(request) + ) + request.timestamp_end = time.time() + return request + def send_request(self, request): raise NotImplementedError() - def read_response(self, request): - response = self.read_response_headers() - response.data.content = b"".join( - self.read_response_body(request, response) - ) - return response - def read_response_headers(self): raise NotImplementedError() @@ -40,6 +40,13 @@ class _HttpTransmissionLayer(base.Layer): raise NotImplementedError() yield "this is a generator" # pragma: no cover + def read_response(self, request): + response = self.read_response_headers() + response.data.content = b"".join( + self.read_response_body(request, response) + ) + return response + def send_response(self, response): if response.data.content is None: raise netlib.exceptions.HttpException("Cannot assemble flow with missing content") @@ -140,8 +147,9 @@ class HttpLayer(base.Layer): self.__initial_server_tls = self.server_tls self.__initial_server_conn = self.server_conn while True: + flow = models.HTTPFlow(self.client_conn, self.server_conn, live=self) try: - request = self.get_request_from_client() + request = self.get_request_from_client(flow) # Make sure that the incoming request matches our expectations self.validate_request(request) except netlib.exceptions.HttpReadDisconnect: @@ -168,7 +176,6 @@ class HttpLayer(base.Layer): if not (self.http_authenticated or self.authenticate(request)): return - flow = models.HTTPFlow(self.client_conn, self.server_conn, live=self) flow.request = request try: @@ -243,13 +250,16 @@ class HttpLayer(base.Layer): if flow: flow.live = False - def get_request_from_client(self): + def get_request_from_client(self, flow): request = self.read_request() + flow.request = request + flow = self.channel.ask("requestheaders", flow) if request.headers.get("expect", "").lower() == "100-continue": # TODO: We may have to use send_response_headers for HTTP2 here. self.send_response(models.expect_continue_response) request.headers.pop("expect") request.body = b"".join(self.read_request_body(request)) + request.timestamp_end = time.time() return request def send_error_response(self, code, message, headers=None): diff --git a/mitmproxy/protocol/http1.py b/mitmproxy/protocol/http1.py index 8698fe31..2f8a15de 100644 --- a/mitmproxy/protocol/http1.py +++ b/mitmproxy/protocol/http1.py @@ -11,11 +11,10 @@ class Http1Layer(http._HttpTransmissionLayer): super(Http1Layer, self).__init__(ctx) self.mode = mode - def read_request(self): - req = http1.read_request( - self.client_conn.rfile, body_size_limit=self.config.options.body_size_limit + def read_request_headers(self): + return models.HTTPRequest.wrap( + http1.read_request_head(self.client_conn.rfile) ) - return models.HTTPRequest.wrap(req) def read_request_body(self, request): expected_size = http1.expected_http_body_size(request) diff --git a/test/mitmproxy/builtins/test_script.py b/test/mitmproxy/builtins/test_script.py index f92765ee..261adb65 100644 --- a/test/mitmproxy/builtins/test_script.py +++ b/test/mitmproxy/builtins/test_script.py @@ -175,7 +175,7 @@ class TestScriptLoader(mastertest.MasterTest): ), [f] ) evts = [i[1] for i in sc.ns.call_log] - assert evts == ['start', 'request', 'responseheaders', 'response', 'done'] + assert evts == ['start', 'requestheaders', 'request', 'responseheaders', 'response', 'done'] with m.handlecontext(): tutils.raises( |