From 6ad8b1a15d725f34990cfe3ae650fa239171a044 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 18 Feb 2012 16:27:09 +1300 Subject: [PATCH] Firm up reverse proxy specification. - Extract proxy spec parsing and unparsing functions. - Add a status indicator in mitmproxy. - Add the "R" keybinding for changing the reverse proxy from within mitmproxy. --- libmproxy/cmdline.py | 2 +- libmproxy/console/__init__.py | 33 +++++++++++++++++++++++++++------ libmproxy/filt.py | 4 +++- libmproxy/flow.py | 11 ++--------- libmproxy/utils.py | 17 +++++++++++++++++ test/test_utils.py | 9 +++++++++ 6 files changed, 59 insertions(+), 17 deletions(-) diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py index d9efe0c25..0e2ecbe55 100644 --- a/libmproxy/cmdline.py +++ b/libmproxy/cmdline.py @@ -67,7 +67,7 @@ def common_options(parser): parser.add_option( "-R", action="store", dest="reverse_proxy", default=None, - help="Reverse proxy: upstream server host:port" + help="Reverse proxy to upstream server: http[s]://host[:port]" ) parser.add_option( "-q", diff --git a/libmproxy/console/__init__.py b/libmproxy/console/__init__.py index d12b16b36..da110cdbb 100644 --- a/libmproxy/console/__init__.py +++ b/libmproxy/console/__init__.py @@ -122,28 +122,32 @@ class StatusBar(common.WWrap): if self.master.client_playback: r.append("[") - r.append(("statusbar_highlight", "cplayback")) + r.append(("key", "cplayback")) r.append(":%s to go]"%self.master.client_playback.count()) if self.master.server_playback: r.append("[") - r.append(("statusbar_highlight", "splayback")) + r.append(("key", "splayback")) r.append(":%s to go]"%self.master.server_playback.count()) if self.master.state.intercept_txt: r.append("[") - r.append(("statusbar_highlight", "i")) + r.append(("key", "i")) r.append(":%s]"%self.master.state.intercept_txt) if self.master.state.limit_txt: r.append("[") - r.append(("statusbar_highlight", "l")) + r.append(("key", "l")) r.append(":%s]"%self.master.state.limit_txt) if self.master.stickycookie_txt: r.append("[") - r.append(("statusbar_highlight", "t")) + r.append(("key", "t")) r.append(":%s]"%self.master.stickycookie_txt) if self.master.stickyauth_txt: r.append("[") - r.append(("statusbar_highlight", "u")) + r.append(("key", "u")) r.append(":%s]"%self.master.stickyauth_txt) + if self.master.server.config.reverse_proxy: + r.append("[") + r.append(("key", "R")) + r.append(":%s]"%utils.unparse_url(*self.master.server.config.reverse_proxy)) opts = [] if self.master.anticache: @@ -667,6 +671,12 @@ class ConsoleMaster(flow.FlowMaster): def set_intercept(self, txt): return self.state.set_intercept(txt) + def set_reverse_proxy(self, txt): + s = utils.parse_proxy_spec(txt) + if not s: + return "Invalid reverse proxy specification" + self.server.config.reverse_proxy = s + def changeview(self, v): if v == "r": self.state.view_body_mode = common.VIEW_BODY_RAW @@ -754,6 +764,17 @@ class ConsoleMaster(flow.FlowMaster): ), self.quit, ) + elif k == "R": + if self.server.config.reverse_proxy: + p = utils.unparse_url(*self.server.config.reverse_proxy) + else: + p = "" + self.prompt( + "Reverse proxy: ", + p, + self.set_reverse_proxy + ) + self.sync_list_view() elif k == "s": if self.script: self.load_script(None) diff --git a/libmproxy/filt.py b/libmproxy/filt.py index 9a2279039..f8abc1c67 100644 --- a/libmproxy/filt.py +++ b/libmproxy/filt.py @@ -212,8 +212,10 @@ class FUrl(_Rex): def __call__(self, o): if isinstance(o, flow.Response): c = o.request - else: + elif isinstance(o, flow.Request): c = o + else: + return False return re.search(self.expr, c.get_url()) diff --git a/libmproxy/flow.py b/libmproxy/flow.py index f9f1093ff..811990353 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -303,13 +303,6 @@ class Request(HTTPMsg): c.headers = self.headers.copy() return c - 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 get_form_urlencoded(self): """ Retrieves the URL-encoded form data, returning a list of (key, @@ -352,7 +345,7 @@ class Request(HTTPMsg): """ Returns a URL string, constructed from the Request's URL compnents. """ - return "%s://%s%s"%(self.scheme, self._hostport(), self.path) + return utils.unparse_url(self.scheme, self.host, self.port, self.path) def set_url(self, url): """ @@ -387,7 +380,7 @@ class Request(HTTPMsg): ] ) if not 'host' in headers: - headers["host"] = [self._hostport()] + headers["host"] = [utils.hostport(self.scheme, self.host, self.port)] content = self.content if content is None: content = "" diff --git a/libmproxy/utils.py b/libmproxy/utils.py index f0e311457..f3c36f8f8 100644 --- a/libmproxy/utils.py +++ b/libmproxy/utils.py @@ -427,6 +427,23 @@ def parse_proxy_spec(url): return p[:3] +def hostport(scheme, host, port): + """ + Returns the host component, with a port specifcation if needed. + """ + if (port, scheme) in [(80, "http"), (443, "https")]: + return host + else: + return "%s:%s"%(host, port) + + +def unparse_url(scheme, host, port, path=""): + """ + Returns a URL string, constructed from the specified compnents. + """ + return "%s://%s%s"%(scheme, hostport(scheme, host, port), path) + + def clean_hanging_newline(t): """ Many editors will silently add a newline to the final line of a diff --git a/test/test_utils.py b/test/test_utils.py index c1e6fdfe6..90585194c 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -208,6 +208,14 @@ class u_parse_proxy_spec(libpry.AutoTree): assert not utils.parse_proxy_spec("foo.com") +class u_unparse_url(libpry.AutoTree): + def test_simple(self): + assert utils.unparse_url("http", "foo.com", 99, "") == "http://foo.com:99" + assert utils.unparse_url("http", "foo.com", 80, "") == "http://foo.com" + assert utils.unparse_url("https", "foo.com", 80, "") == "https://foo.com:80" + assert utils.unparse_url("https", "foo.com", 443, "") == "https://foo.com" + + class u_parse_url(libpry.AutoTree): def test_simple(self): assert not utils.parse_url("") @@ -262,6 +270,7 @@ tests = [ uLRUCache(), u_parse_url(), u_parse_proxy_spec(), + u_unparse_url(), u_parse_size(), uclean_hanging_newline() ]