From 7a3b871b330692021452221e60310ee7fee99ce3 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 4 Aug 2011 09:26:26 +1200 Subject: Request class now has a clean pydoc profile. --- libmproxy/console.py | 4 ++-- libmproxy/dump.py | 2 +- libmproxy/filt.py | 30 +++++++++++------------ libmproxy/flow.py | 68 +++++++++++++++++++++++++++++++++++++++------------- libmproxy/proxy.py | 2 +- test/test_console.py | 4 ++-- test/test_dump.py | 2 +- test/test_flow.py | 4 ++-- 8 files changed, 76 insertions(+), 40 deletions(-) diff --git a/libmproxy/console.py b/libmproxy/console.py index 66efffe9..c798cf43 100644 --- a/libmproxy/console.py +++ b/libmproxy/console.py @@ -82,7 +82,7 @@ def format_flow(f, focus, extended=False, padding=2): " ", ( "text" if (f.response or f.error) else "title", - f.request.url(), + f.request.get_url(), ), ]) if f.response or f.error or f.request.is_replay(): @@ -465,7 +465,7 @@ class ConnectionView(WWrap): headers.read(fp) conn.headers = headers elif part == "u" and self.state.view_flow_mode == VIEW_FLOW_REQUEST: - self.master.prompt_edit("URL", conn.url(), self.set_url) + self.master.prompt_edit("URL", conn.get_url(), self.set_url) elif part == "m" and self.state.view_flow_mode == VIEW_FLOW_REQUEST: self.master.prompt_onekey("Method", self.methods, self.edit_method) elif part == "c" and self.state.view_flow_mode == VIEW_FLOW_RESPONSE: diff --git a/libmproxy/dump.py b/libmproxy/dump.py index 86f2fea2..41b5627f 100644 --- a/libmproxy/dump.py +++ b/libmproxy/dump.py @@ -44,7 +44,7 @@ def str_request(req): c = req.client_conn.address[0] else: c = "[replay]" - r = "%s %s %s"%(c, req.method, req.url()) + r = "%s %s %s"%(c, req.method, req.get_url()) if req.stickycookie: r = "[stickycookie] " + r return r diff --git a/libmproxy/filt.py b/libmproxy/filt.py index c3de6c11..d4efaf05 100644 --- a/libmproxy/filt.py +++ b/libmproxy/filt.py @@ -60,14 +60,14 @@ class FReq(_Action): code = "q" help = "Match request" def __call__(self, conn): - return not conn.is_response() + return not conn._is_response() class FResp(_Action): code = "s" help = "Match response" def __call__(self, conn): - return conn.is_response() + return conn._is_response() class _Rex(_Action): @@ -91,7 +91,7 @@ class FContentType(_Rex): def __call__(self, o): if _check_content_type(self.expr, o): return True - elif o.is_response() and _check_content_type(self.expr, o.request): + elif o._is_response() and _check_content_type(self.expr, o.request): return True else: return False @@ -101,7 +101,7 @@ class FRequestContentType(_Rex): code = "tq" help = "Request Content-Type header" def __call__(self, o): - if o.is_response(): + if o._is_response(): return _check_content_type(self.expr, o.request) else: return _check_content_type(self.expr, o) @@ -111,7 +111,7 @@ class FResponseContentType(_Rex): code = "ts" help = "Request Content-Type header" def __call__(self, o): - if o.is_response(): + if o._is_response(): return _check_content_type(self.expr, o) else: return False @@ -122,7 +122,7 @@ class FHead(_Rex): help = "Header" def __call__(self, o): val = o.headers.match_re(self.expr) - if not val and o.is_response(): + if not val and o._is_response(): val = o.request.headers.match_re(self.expr) return val @@ -131,7 +131,7 @@ class FHeadRequest(_Rex): code = "hq" help = "Request header" def __call__(self, o): - if o.is_response(): + if o._is_response(): h = o.request.headers else: h = o.headers @@ -142,7 +142,7 @@ class FHeadResponse(_Rex): code = "hs" help = "Response header" def __call__(self, o): - if not o.is_response(): + if not o._is_response(): return False return o.headers.match_re(self.expr) @@ -153,7 +153,7 @@ class FBod(_Rex): def __call__(self, o): if o.content and re.search(self.expr, o.content): return True - elif o.is_response() and o.request.content and re.search(self.expr, o.request.content): + elif o._is_response() and o.request.content and re.search(self.expr, o.request.content): return True return False @@ -162,9 +162,9 @@ class FBodRequest(_Rex): code = "bq" help = "Request body" def __call__(self, o): - if o.is_response() and o.request.content and re.search(self.expr, o.request.content): + if o._is_response() and o.request.content and re.search(self.expr, o.request.content): return True - elif not o.is_response() and o.content and re.search(self.expr, o.content): + elif not o._is_response() and o.content and re.search(self.expr, o.content): return True return False @@ -173,7 +173,7 @@ class FBodResponse(_Rex): code = "bs" help = "Response body" def __call__(self, o): - if not o.is_response(): + if not o._is_response(): return False elif o.content and re.search(self.expr, o.content): return True @@ -191,11 +191,11 @@ class FUrl(_Rex): return klass(*toks) def __call__(self, o): - if o.is_response(): + if o._is_response(): c = o.request else: c = o - return re.search(self.expr, c.url()) + return re.search(self.expr, c.get_url()) class _Int(_Action): @@ -207,7 +207,7 @@ class FCode(_Int): code = "c" help = "HTTP response code" def __call__(self, o): - if o.is_response(): + if o._is_response(): return o.code == self.num return False diff --git a/libmproxy/flow.py b/libmproxy/flow.py index 42a234ec..6cda6bd2 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -162,8 +162,23 @@ class HTTPMsg(controller.Msg): class Request(HTTPMsg): - FMT = '%s %s HTTP/1.1\r\n%s\r\n%s' - FMT_PROXY = '%s %s://%s:%s%s HTTP/1.1\r\n%s\r\n%s' + """ + An HTTP request. + + Exposes the following attributes: + + client_conn: ClientConnection object, or None if this is a replay. + headers: A Headers object + content: The content of the request, or None + + scheme: URL scheme (http/https) + host: Host portion of the URL + port: Destination port + path: The path portion of the URL + + timestamp: Time of the request. + method: HTTP method + """ def __init__(self, client_conn, host, port, scheme, method, path, headers, content, timestamp=None): self.client_conn = client_conn self.host, self.port, self.scheme = host, port, scheme @@ -205,10 +220,13 @@ class Request(HTTPMsg): e for e in encoding.ENCODINGS if e in self.headers["accept-encoding"][0] ])] - def set_replay(self): + def _set_replay(self): self.client_conn = None def is_replay(self): + """ + Is this request a replay? + """ if self.client_conn: return False else: @@ -265,28 +283,40 @@ class Request(HTTPMsg): return self._get_state() == other._get_state() def copy(self): + """ + Returns a copy of this object. + """ c = copy.copy(self) c.headers = self.headers.copy() return c - def hostport(self): + def _hostport(self): if (self.port, self.scheme) in [(80, "http"), (443, "https")]: host = self.host else: host = "%s:%s"%(self.host, self.port) return host - def url(self): - return "%s://%s%s"%(self.scheme, self.hostport(), self.path) + def get_url(self): + """ + Returns a URL string, constructed from the Request's URL compnents. + """ + return "%s://%s%s"%(self.scheme, self._hostport(), self.path) def set_url(self, url): + """ + Parses a URL specification, and updates the Request's information + accordingly. + + Returns False if the URL was invalid, True if the request succeeded. + """ parts = utils.parse_url(url) if not parts: return False self.scheme, self.host, self.port, self.path = parts return True - def is_response(self): + def _is_response(self): return False def _assemble(self, _proxy = False): @@ -294,6 +324,9 @@ class Request(HTTPMsg): Assembles the request for transmission to the server. We make some modifications to make sure interception works properly. """ + FMT = '%s %s HTTP/1.1\r\n%s\r\n%s' + FMT_PROXY = '%s %s://%s:%s%s HTTP/1.1\r\n%s\r\n%s' + headers = self.headers.copy() utils.del_all( headers, @@ -306,7 +339,7 @@ class Request(HTTPMsg): ] ) if not 'host' in headers: - headers["host"] = [self.hostport()] + headers["host"] = [self._hostport()] content = self.content if content is not None: headers["content-length"] = [str(len(content))] @@ -315,9 +348,9 @@ class Request(HTTPMsg): if self.close: headers["connection"] = ["close"] if not _proxy: - return self.FMT % (self.method, self.path, str(headers), content) + return FMT % (self.method, self.path, str(headers), content) else: - return self.FMT_PROXY % (self.method, self.scheme, self.host, self.port, self.path, str(headers), content) + return FMT_PROXY % (self.method, self.scheme, self.host, self.port, self.path, str(headers), content) def replace(self, pattern, repl, *args, **kwargs): """ @@ -333,7 +366,6 @@ class Request(HTTPMsg): class Response(HTTPMsg): - FMT = '%s\r\n%s\r\n%s' def __init__(self, request, code, msg, headers, content, timestamp=None): self.request = request self.code, self.msg = code, msg @@ -392,10 +424,13 @@ class Response(HTTPMsg): if c: self.headers["set-cookie"] = c - def set_replay(self): + def _set_replay(self): self.replay = True def is_replay(self): + """ + Is this response a replay? + """ return self.replay def _load_state(self, state): @@ -433,7 +468,7 @@ class Response(HTTPMsg): c.headers = self.headers.copy() return c - def is_response(self): + def _is_response(self): return True def _assemble(self): @@ -441,6 +476,7 @@ class Response(HTTPMsg): Assembles the response for transmission to the client. We make some modifications to make sure interception works properly. """ + FMT = '%s\r\n%s\r\n%s' headers = self.headers.copy() utils.del_all( headers, @@ -455,7 +491,7 @@ class Response(HTTPMsg): headers["connection"] = ["close"] proto = "HTTP/1.1 %s %s"%(self.code, str(self.msg)) data = (proto, str(headers), content) - return self.FMT%data + return FMT%data def replace(self, pattern, repl, *args, **kwargs): """ @@ -1035,7 +1071,7 @@ class FlowMaster(controller.Master): if not rflow: return None response = Response._from_state(flow.request, rflow.response._get_state()) - response.set_replay() + response._set_replay() flow.response = response if self.refresh_server_playback: response.refresh() @@ -1103,7 +1139,7 @@ class FlowMaster(controller.Master): if f.intercepting: return "Can't replay while intercepting..." if f.request: - f.request.set_replay() + f.request._set_replay() if f.request.content: f.request.headers["content-length"] = [str(len(f.request.content))] f.response = None diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py index 81b5aeb4..e95b38e2 100644 --- a/libmproxy/proxy.py +++ b/libmproxy/proxy.py @@ -248,7 +248,7 @@ class ProxyHandler(SocketServer.StreamRequestHandler): cc.close = True return - if request.is_response(): + if request._is_response(): response = request request = False response = response._send(self.mqueue) diff --git a/test/test_console.py b/test/test_console.py index f76b086f..a935c146 100644 --- a/test/test_console.py +++ b/test/test_console.py @@ -103,8 +103,8 @@ class uformat_flow(libpry.AutoTree): f.request = f.response.request f.backup() - f.request.set_replay() - f.response.set_replay() + f.request._set_replay() + f.response._set_replay() assert ('method', '[replay]') in console.format_flow(f, True) assert ('method', '[replay]') in console.format_flow(f, True, True) diff --git a/test/test_dump.py b/test/test_dump.py index 247ab15b..808b3a7e 100644 --- a/test/test_dump.py +++ b/test/test_dump.py @@ -7,7 +7,7 @@ import tutils class uStrFuncs(libpry.AutoTree): def test_all(self): t = tutils.tresp() - t.set_replay() + t._set_replay() dump.str_response(t) t = tutils.treq() diff --git a/test/test_flow.py b/test/test_flow.py index 4c4f7bf8..fa49aecd 100644 --- a/test/test_flow.py +++ b/test/test_flow.py @@ -571,10 +571,10 @@ class uRequest(libpry.AutoTree): h["test"] = ["test"] c = flow.ClientConnect(("addr", 2222)) r = flow.Request(c, "host", 22, "https", "GET", "/", h, "content") - u = r.url() + u = r.get_url() assert r.set_url(u) assert not r.set_url("") - assert r.url() == u + assert r.get_url() == u assert r._assemble() r2 = r.copy() -- cgit v1.2.3