mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 18:18:25 +00:00
improve HTTPRequest syntax
This commit is contained in:
parent
cd43c5ba9c
commit
2f44b26b4c
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
def request(context, flow):
|
def request(context, flow):
|
||||||
if "application/x-www-form-urlencoded" in flow.request.headers["content-type"]:
|
if "application/x-www-form-urlencoded" in flow.request.headers["content-type"]:
|
||||||
frm = flow.request.get_form_urlencoded()
|
frm = flow.request.form_urlencoded
|
||||||
frm["mitmproxy"] = ["rocks"]
|
frm["mitmproxy"] = ["rocks"]
|
||||||
flow.request.set_form_urlencoded(frm)
|
flow.request.form_urlencoded = frm
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
def request(context, flow):
|
def request(context, flow):
|
||||||
q = flow.request.get_query()
|
q = flow.request.query
|
||||||
if q:
|
if q:
|
||||||
q["mitmproxy"] = ["rocks"]
|
q["mitmproxy"] = ["rocks"]
|
||||||
flow.request.set_query(q)
|
flow.request.query = q
|
||||||
|
|
||||||
|
@ -7,12 +7,12 @@ This example shows two ways to redirect flows to other destinations.
|
|||||||
|
|
||||||
|
|
||||||
def request(context, flow):
|
def request(context, flow):
|
||||||
if flow.request.get_host(hostheader=True).endswith("example.com"):
|
if flow.request.pretty_host(hostheader=True).endswith("example.com"):
|
||||||
resp = HTTPResponse(
|
resp = HTTPResponse(
|
||||||
[1, 1], 200, "OK",
|
[1, 1], 200, "OK",
|
||||||
ODictCaseless([["Content-Type", "text/html"]]),
|
ODictCaseless([["Content-Type", "text/html"]]),
|
||||||
"helloworld")
|
"helloworld")
|
||||||
flow.request.reply(resp)
|
flow.request.reply(resp)
|
||||||
if flow.request.get_host(hostheader=True).endswith("example.org"):
|
if flow.request.pretty_host(hostheader=True).endswith("example.org"):
|
||||||
flow.request.host = "mitmproxy.org"
|
flow.request.host = "mitmproxy.org"
|
||||||
flow.request.headers["Host"] = ["mitmproxy.org"]
|
flow.request.update_host_header()
|
||||||
|
@ -177,7 +177,7 @@ def format_flow(f, focus, extended=False, hostheader=False, padding=2):
|
|||||||
req_is_replay = f.request.is_replay,
|
req_is_replay = f.request.is_replay,
|
||||||
req_method = f.request.method,
|
req_method = f.request.method,
|
||||||
req_acked = f.request.reply.acked,
|
req_acked = f.request.reply.acked,
|
||||||
req_url = f.request.get_url(hostheader=hostheader),
|
req_url = f.request.pretty_url(hostheader=hostheader),
|
||||||
|
|
||||||
err_msg = f.error.msg if f.error else None,
|
err_msg = f.error.msg if f.error else None,
|
||||||
resp_code = f.response.code if f.response else None,
|
resp_code = f.response.code if f.response else None,
|
||||||
|
@ -528,7 +528,9 @@ class FlowView(common.WWrap):
|
|||||||
|
|
||||||
def set_url(self, url):
|
def set_url(self, url):
|
||||||
request = self.flow.request
|
request = self.flow.request
|
||||||
if not request.set_url(str(url)):
|
try:
|
||||||
|
request.url = str(url)
|
||||||
|
except ValueError:
|
||||||
return "Invalid URL."
|
return "Invalid URL."
|
||||||
self.master.refresh_flow(self.flow)
|
self.master.refresh_flow(self.flow)
|
||||||
|
|
||||||
@ -552,17 +554,17 @@ class FlowView(common.WWrap):
|
|||||||
conn.headers = flow.ODictCaseless(lst)
|
conn.headers = flow.ODictCaseless(lst)
|
||||||
|
|
||||||
def set_query(self, lst, conn):
|
def set_query(self, lst, conn):
|
||||||
conn.set_query(flow.ODict(lst))
|
conn.query = flow.ODict(lst)
|
||||||
|
|
||||||
def set_path_components(self, lst, conn):
|
def set_path_components(self, lst, conn):
|
||||||
conn.set_path_components([i[0] for i in lst])
|
conn.path_components = [i[0] for i in lst]
|
||||||
|
|
||||||
def set_form(self, lst, conn):
|
def set_form(self, lst, conn):
|
||||||
conn.set_form_urlencoded(flow.ODict(lst))
|
conn.form_urlencoded = flow.ODict(lst)
|
||||||
|
|
||||||
def edit_form(self, conn):
|
def edit_form(self, conn):
|
||||||
self.master.view_grideditor(
|
self.master.view_grideditor(
|
||||||
grideditor.URLEncodedFormEditor(self.master, conn.get_form_urlencoded().lst, self.set_form, conn)
|
grideditor.URLEncodedFormEditor(self.master, conn.form_urlencoded.lst, self.set_form, conn)
|
||||||
)
|
)
|
||||||
|
|
||||||
def edit_form_confirm(self, key, conn):
|
def edit_form_confirm(self, key, conn):
|
||||||
@ -587,7 +589,7 @@ class FlowView(common.WWrap):
|
|||||||
c = self.master.spawn_editor(conn.content or "")
|
c = self.master.spawn_editor(conn.content or "")
|
||||||
conn.content = c.rstrip("\n") # what?
|
conn.content = c.rstrip("\n") # what?
|
||||||
elif part == "f":
|
elif part == "f":
|
||||||
if not conn.get_form_urlencoded() and conn.content:
|
if not conn.form_urlencoded and conn.content:
|
||||||
self.master.prompt_onekey(
|
self.master.prompt_onekey(
|
||||||
"Existing body is not a URL-encoded form. Clear and edit?",
|
"Existing body is not a URL-encoded form. Clear and edit?",
|
||||||
[
|
[
|
||||||
@ -602,13 +604,13 @@ class FlowView(common.WWrap):
|
|||||||
elif part == "h":
|
elif part == "h":
|
||||||
self.master.view_grideditor(grideditor.HeaderEditor(self.master, conn.headers.lst, self.set_headers, conn))
|
self.master.view_grideditor(grideditor.HeaderEditor(self.master, conn.headers.lst, self.set_headers, conn))
|
||||||
elif part == "p":
|
elif part == "p":
|
||||||
p = conn.get_path_components()
|
p = conn.path_components
|
||||||
p = [[i] for i in p]
|
p = [[i] for i in p]
|
||||||
self.master.view_grideditor(grideditor.PathEditor(self.master, p, self.set_path_components, conn))
|
self.master.view_grideditor(grideditor.PathEditor(self.master, p, self.set_path_components, conn))
|
||||||
elif part == "q":
|
elif part == "q":
|
||||||
self.master.view_grideditor(grideditor.QueryEditor(self.master, conn.get_query().lst, self.set_query, conn))
|
self.master.view_grideditor(grideditor.QueryEditor(self.master, conn.query.lst, self.set_query, conn))
|
||||||
elif part == "u" and self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
|
elif part == "u" and self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
|
||||||
self.master.prompt_edit("URL", conn.get_url(), self.set_url)
|
self.master.prompt_edit("URL", conn.url, self.set_url)
|
||||||
elif part == "m" and self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
|
elif part == "m" and self.state.view_flow_mode == common.VIEW_FLOW_REQUEST:
|
||||||
self.master.prompt_onekey("Method", self.method_options, self.edit_method)
|
self.master.prompt_onekey("Method", self.method_options, self.edit_method)
|
||||||
elif part == "c" and self.state.view_flow_mode == common.VIEW_FLOW_RESPONSE:
|
elif part == "c" and self.state.view_flow_mode == common.VIEW_FLOW_RESPONSE:
|
||||||
|
@ -55,7 +55,7 @@ def str_request(f, showhost):
|
|||||||
c = f.client_conn.address.host
|
c = f.client_conn.address.host
|
||||||
else:
|
else:
|
||||||
c = "[replay]"
|
c = "[replay]"
|
||||||
r = "%s %s %s"%(c, f.request.method, f.request.get_url(showhost, f))
|
r = "%s %s %s"%(c, f.request.method, f.request.pretty_url(showhost))
|
||||||
if f.request.stickycookie:
|
if f.request.stickycookie:
|
||||||
r = "[stickycookie] " + r
|
r = "[stickycookie] " + r
|
||||||
return r
|
return r
|
||||||
|
@ -208,7 +208,7 @@ class FDomain(_Rex):
|
|||||||
code = "d"
|
code = "d"
|
||||||
help = "Domain"
|
help = "Domain"
|
||||||
def __call__(self, f):
|
def __call__(self, f):
|
||||||
return bool(re.search(self.expr, f.request.get_host(False, f), re.IGNORECASE))
|
return bool(re.search(self.expr, f.request.host, re.IGNORECASE))
|
||||||
|
|
||||||
|
|
||||||
class FUrl(_Rex):
|
class FUrl(_Rex):
|
||||||
@ -222,7 +222,7 @@ class FUrl(_Rex):
|
|||||||
return klass(*toks)
|
return klass(*toks)
|
||||||
|
|
||||||
def __call__(self, f):
|
def __call__(self, f):
|
||||||
return re.search(self.expr, f.request.get_url(False, f))
|
return re.search(self.expr, f.request.url)
|
||||||
|
|
||||||
|
|
||||||
class _Int(_Action):
|
class _Int(_Action):
|
||||||
|
@ -260,8 +260,8 @@ class StickyCookieState:
|
|||||||
Returns a (domain, port, path) tuple.
|
Returns a (domain, port, path) tuple.
|
||||||
"""
|
"""
|
||||||
return (
|
return (
|
||||||
m["domain"] or f.request.get_host(False, f),
|
m["domain"] or f.request.host,
|
||||||
f.request.get_port(f),
|
f.request.port,
|
||||||
m["path"] or "/"
|
m["path"] or "/"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ class StickyCookieState:
|
|||||||
c = Cookie.SimpleCookie(str(i))
|
c = Cookie.SimpleCookie(str(i))
|
||||||
m = c.values()[0]
|
m = c.values()[0]
|
||||||
k = self.ckey(m, f)
|
k = self.ckey(m, f)
|
||||||
if self.domain_match(f.request.get_host(False, f), k[0]):
|
if self.domain_match(f.request.host, k[0]):
|
||||||
self.jar[self.ckey(m, f)] = m
|
self.jar[self.ckey(m, f)] = m
|
||||||
|
|
||||||
def handle_request(self, f):
|
def handle_request(self, f):
|
||||||
@ -287,8 +287,8 @@ class StickyCookieState:
|
|||||||
if f.match(self.flt):
|
if f.match(self.flt):
|
||||||
for i in self.jar.keys():
|
for i in self.jar.keys():
|
||||||
match = [
|
match = [
|
||||||
self.domain_match(f.request.get_host(False, f), i[0]),
|
self.domain_match(f.request.host, i[0]),
|
||||||
f.request.get_port(f) == i[1],
|
f.request.port == i[1],
|
||||||
f.request.path.startswith(i[2])
|
f.request.path.startswith(i[2])
|
||||||
]
|
]
|
||||||
if all(match):
|
if all(match):
|
||||||
@ -307,7 +307,7 @@ class StickyAuthState:
|
|||||||
self.hosts = {}
|
self.hosts = {}
|
||||||
|
|
||||||
def handle_request(self, f):
|
def handle_request(self, f):
|
||||||
host = f.request.get_host(False, f)
|
host = f.request.host
|
||||||
if "authorization" in f.request.headers:
|
if "authorization" in f.request.headers:
|
||||||
self.hosts[host] = f.request.headers["authorization"]
|
self.hosts[host] = f.request.headers["authorization"]
|
||||||
elif f.match(self.flt):
|
elif f.match(self.flt):
|
||||||
|
@ -411,7 +411,14 @@ class HTTPRequest(HTTPMessage):
|
|||||||
e for e in encoding.ENCODINGS if e in self.headers["accept-encoding"][0]
|
e for e in encoding.ENCODINGS if e in self.headers["accept-encoding"][0]
|
||||||
)]
|
)]
|
||||||
|
|
||||||
def get_form_urlencoded(self):
|
def update_host_header(self):
|
||||||
|
"""
|
||||||
|
Update the host header to reflect the current target.
|
||||||
|
"""
|
||||||
|
self.headers["Host"] = [self.host]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def form_urlencoded(self):
|
||||||
"""
|
"""
|
||||||
Retrieves the URL-encoded form data, returning an ODict object.
|
Retrieves the URL-encoded form data, returning an ODict object.
|
||||||
Returns an empty ODict if there is no data or the content-type
|
Returns an empty ODict if there is no data or the content-type
|
||||||
@ -421,7 +428,8 @@ class HTTPRequest(HTTPMessage):
|
|||||||
return ODict(utils.urldecode(self.content))
|
return ODict(utils.urldecode(self.content))
|
||||||
return ODict([])
|
return ODict([])
|
||||||
|
|
||||||
def set_form_urlencoded(self, odict):
|
@form_urlencoded.setter
|
||||||
|
def form_urlencoded(self, odict):
|
||||||
"""
|
"""
|
||||||
Sets the body to the URL-encoded form data, and adds the
|
Sets the body to the URL-encoded form data, and adds the
|
||||||
appropriate content-type header. Note that this will destory the
|
appropriate content-type header. Note that this will destory the
|
||||||
@ -432,16 +440,18 @@ class HTTPRequest(HTTPMessage):
|
|||||||
self.headers["Content-Type"] = [HDR_FORM_URLENCODED]
|
self.headers["Content-Type"] = [HDR_FORM_URLENCODED]
|
||||||
self.content = utils.urlencode(odict.lst)
|
self.content = utils.urlencode(odict.lst)
|
||||||
|
|
||||||
def get_path_components(self, f):
|
@property
|
||||||
|
def path_components(self):
|
||||||
"""
|
"""
|
||||||
Returns the path components of the URL as a list of strings.
|
Returns the path components of the URL as a list of strings.
|
||||||
|
|
||||||
Components are unquoted.
|
Components are unquoted.
|
||||||
"""
|
"""
|
||||||
_, _, path, _, _, _ = urlparse.urlparse(self.get_url(False, f))
|
_, _, path, _, _, _ = urlparse.urlparse(self.url)
|
||||||
return [urllib.unquote(i) for i in path.split("/") if i]
|
return [urllib.unquote(i) for i in path.split("/") if i]
|
||||||
|
|
||||||
def set_path_components(self, lst, f):
|
@path_components.setter
|
||||||
|
def path_components(self, lst):
|
||||||
"""
|
"""
|
||||||
Takes a list of strings, and sets the path component of the URL.
|
Takes a list of strings, and sets the path component of the URL.
|
||||||
|
|
||||||
@ -449,32 +459,34 @@ class HTTPRequest(HTTPMessage):
|
|||||||
"""
|
"""
|
||||||
lst = [urllib.quote(i, safe="") for i in lst]
|
lst = [urllib.quote(i, safe="") for i in lst]
|
||||||
path = "/" + "/".join(lst)
|
path = "/" + "/".join(lst)
|
||||||
scheme, netloc, _, params, query, fragment = urlparse.urlparse(self.get_url(False, f))
|
scheme, netloc, _, params, query, fragment = urlparse.urlparse(self.url)
|
||||||
self.set_url(urlparse.urlunparse([scheme, netloc, path, params, query, fragment]), f)
|
self.url = urlparse.urlunparse([scheme, netloc, path, params, query, fragment])
|
||||||
|
|
||||||
def get_query(self, f):
|
@property
|
||||||
|
def query(self):
|
||||||
"""
|
"""
|
||||||
Gets the request query string. Returns an ODict object.
|
Gets the request query string. Returns an ODict object.
|
||||||
"""
|
"""
|
||||||
_, _, _, _, query, _ = urlparse.urlparse(self.get_url(False, f))
|
_, _, _, _, query, _ = urlparse.urlparse(self.url)
|
||||||
if query:
|
if query:
|
||||||
return ODict(utils.urldecode(query))
|
return ODict(utils.urldecode(query))
|
||||||
return ODict([])
|
return ODict([])
|
||||||
|
|
||||||
def set_query(self, odict, f):
|
@query.setter
|
||||||
|
def query(self, odict):
|
||||||
"""
|
"""
|
||||||
Takes an ODict object, and sets the request query string.
|
Takes an ODict object, and sets the request query string.
|
||||||
"""
|
"""
|
||||||
scheme, netloc, path, params, _, fragment = urlparse.urlparse(self.get_url(False, f))
|
scheme, netloc, path, params, _, fragment = urlparse.urlparse(self.url)
|
||||||
query = utils.urlencode(odict.lst)
|
query = utils.urlencode(odict.lst)
|
||||||
self.set_url(urlparse.urlunparse([scheme, netloc, path, params, query, fragment]), f)
|
self.url = urlparse.urlunparse([scheme, netloc, path, params, query, fragment])
|
||||||
|
|
||||||
def get_host(self, hostheader, flow):
|
def pretty_host(self, hostheader):
|
||||||
"""
|
"""
|
||||||
Heuristic to get the host of the request.
|
Heuristic to get the host of the request.
|
||||||
|
|
||||||
Note that get_host() does not always return the TCP destination of the request,
|
Note that pretty_host() does not always return the TCP destination of the request,
|
||||||
e.g. on a transparently intercepted request to an unrelated HTTP proxy.
|
e.g. if an upstream proxy is in place
|
||||||
|
|
||||||
If hostheader is set to True, the Host: header will be used as additional (and preferred) data source.
|
If hostheader is set to True, the Host: header will be used as additional (and preferred) data source.
|
||||||
This is handy in transparent mode, where only the ip of the destination is known, but not the
|
This is handy in transparent mode, where only the ip of the destination is known, but not the
|
||||||
@ -484,54 +496,27 @@ class HTTPRequest(HTTPMessage):
|
|||||||
if hostheader:
|
if hostheader:
|
||||||
host = self.headers.get_first("host")
|
host = self.headers.get_first("host")
|
||||||
if not host:
|
if not host:
|
||||||
if self.host:
|
|
||||||
host = self.host
|
host = self.host
|
||||||
else:
|
|
||||||
for s in flow.server_conn.state:
|
|
||||||
if s[0] == "http" and s[1]["state"] == "connect":
|
|
||||||
host = s[1]["host"]
|
|
||||||
break
|
|
||||||
if not host:
|
|
||||||
host = flow.server_conn.address.host
|
|
||||||
host = host.encode("idna")
|
host = host.encode("idna")
|
||||||
return host
|
return host
|
||||||
|
|
||||||
def get_scheme(self, flow):
|
def pretty_url(self, hostheader):
|
||||||
"""
|
|
||||||
Returns the request port, either from the request itself or from the flow's server connection
|
|
||||||
"""
|
|
||||||
if self.scheme:
|
|
||||||
return self.scheme
|
|
||||||
if self.form_out == "authority": # On SSLed connections, the original CONNECT request is still unencrypted.
|
|
||||||
return "http"
|
|
||||||
return "https" if flow.server_conn.ssl_established else "http"
|
|
||||||
|
|
||||||
def get_port(self, flow):
|
|
||||||
"""
|
|
||||||
Returns the request port, either from the request itself or from the flow's server connection
|
|
||||||
"""
|
|
||||||
if self.port:
|
|
||||||
return self.port
|
|
||||||
for s in flow.server_conn.state:
|
|
||||||
if s[0] == "http" and s[1].get("state") == "connect":
|
|
||||||
return s[1]["port"]
|
|
||||||
return flow.server_conn.address.port
|
|
||||||
|
|
||||||
def get_url(self, hostheader, flow):
|
|
||||||
"""
|
|
||||||
Returns a URL string, constructed from the Request's URL components.
|
|
||||||
|
|
||||||
If hostheader is True, we use the value specified in the request
|
|
||||||
Host header to construct the URL.
|
|
||||||
"""
|
|
||||||
if self.form_out == "authority": # upstream proxy mode
|
if self.form_out == "authority": # upstream proxy mode
|
||||||
return "%s:%s" % (self.get_host(hostheader, flow), self.get_port(flow))
|
return "%s:%s" % (self.pretty_host(hostheader), self.port)
|
||||||
return utils.unparse_url(self.get_scheme(flow),
|
return utils.unparse_url(self.scheme,
|
||||||
self.get_host(hostheader, flow),
|
self.pretty_host(hostheader),
|
||||||
self.get_port(flow),
|
self.port,
|
||||||
self.path).encode('ascii')
|
self.path).encode('ascii')
|
||||||
|
|
||||||
def set_url(self, url, flow):
|
@property
|
||||||
|
def url(self):
|
||||||
|
"""
|
||||||
|
Returns a URL string, constructed from the Request's URL components.
|
||||||
|
"""
|
||||||
|
return self.pretty_url(False)
|
||||||
|
|
||||||
|
@url.setter
|
||||||
|
def url(self, url):
|
||||||
"""
|
"""
|
||||||
Parses a URL specification, and updates the Request's information
|
Parses a URL specification, and updates the Request's information
|
||||||
accordingly.
|
accordingly.
|
||||||
@ -540,31 +525,11 @@ class HTTPRequest(HTTPMessage):
|
|||||||
"""
|
"""
|
||||||
parts = http.parse_url(url)
|
parts = http.parse_url(url)
|
||||||
if not parts:
|
if not parts:
|
||||||
return False
|
raise ValueError("Invalid URL: %s" % url)
|
||||||
scheme, host, port, path = parts
|
self.scheme, self.host, self.port, self.path = parts
|
||||||
is_ssl = (True if scheme == "https" else False)
|
|
||||||
|
|
||||||
self.path = path
|
@property
|
||||||
|
def cookies(self):
|
||||||
if host != self.get_host(False, flow) or port != self.get_port(flow):
|
|
||||||
if flow.live:
|
|
||||||
flow.live.change_server((host, port), ssl=is_ssl)
|
|
||||||
else:
|
|
||||||
# There's not live server connection, we're just changing the attributes here.
|
|
||||||
flow.server_conn = ServerConnection((host, port))
|
|
||||||
flow.server_conn.ssl_established = is_ssl
|
|
||||||
|
|
||||||
# If this is an absolute request, replace the attributes on the request object as well.
|
|
||||||
if self.host:
|
|
||||||
self.host = host
|
|
||||||
if self.port:
|
|
||||||
self.port = port
|
|
||||||
if self.scheme:
|
|
||||||
self.scheme = scheme
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_cookies(self):
|
|
||||||
cookie_headers = self.headers.get("cookie")
|
cookie_headers = self.headers.get("cookie")
|
||||||
if not cookie_headers:
|
if not cookie_headers:
|
||||||
return None
|
return None
|
||||||
@ -760,7 +725,8 @@ class HTTPResponse(HTTPMessage):
|
|||||||
if c:
|
if c:
|
||||||
self.headers["set-cookie"] = c
|
self.headers["set-cookie"] = c
|
||||||
|
|
||||||
def get_cookies(self):
|
@property
|
||||||
|
def cookies(self):
|
||||||
cookie_headers = self.headers.get("set-cookie")
|
cookie_headers = self.headers.get("set-cookie")
|
||||||
if not cookie_headers:
|
if not cookie_headers:
|
||||||
return None
|
return None
|
||||||
@ -1127,12 +1093,12 @@ class HTTPHandler(ProtocolHandler):
|
|||||||
if not request.host:
|
if not request.host:
|
||||||
# Host/Port Complication: In upstream mode, use the server we CONNECTed to,
|
# Host/Port Complication: In upstream mode, use the server we CONNECTed to,
|
||||||
# not the upstream proxy.
|
# not the upstream proxy.
|
||||||
|
if flow.server_conn:
|
||||||
for s in flow.server_conn.state:
|
for s in flow.server_conn.state:
|
||||||
if s[0] == "http" and s[1]["state"] == "connect":
|
if s[0] == "http" and s[1]["state"] == "connect":
|
||||||
request.host, request.port = s[1]["host"], s[1]["port"]
|
request.host, request.port = s[1]["host"], s[1]["port"]
|
||||||
if not request.host:
|
if not request.host and flow.server_conn:
|
||||||
request.host = flow.server_conn.address.host
|
request.host, request.port = flow.server_conn.address.host, flow.server_conn.address.port
|
||||||
request.port = flow.server_conn.address.port
|
|
||||||
|
|
||||||
# Now we can process the request.
|
# Now we can process the request.
|
||||||
if request.form_in == "authority":
|
if request.form_in == "authority":
|
||||||
@ -1242,7 +1208,9 @@ class RequestReplayThread(threading.Thread):
|
|||||||
|
|
||||||
r.form_out = self.config.http_form_out
|
r.form_out = self.config.http_form_out
|
||||||
server_address, server_ssl = False, False
|
server_address, server_ssl = False, False
|
||||||
if self.config.get_upstream_server:
|
# If the flow is live, r.host is already the correct upstream server unless modified by a script.
|
||||||
|
# If modified by a script, we probably want to keep the modified destination.
|
||||||
|
if self.config.get_upstream_server and not self.flow.live:
|
||||||
try:
|
try:
|
||||||
# this will fail in transparent mode
|
# this will fail in transparent mode
|
||||||
upstream_info = self.config.get_upstream_server(self.flow.client_conn)
|
upstream_info = self.config.get_upstream_server(self.flow.client_conn)
|
||||||
@ -1251,17 +1219,16 @@ class RequestReplayThread(threading.Thread):
|
|||||||
except proxy.ProxyError:
|
except proxy.ProxyError:
|
||||||
pass
|
pass
|
||||||
if not server_address:
|
if not server_address:
|
||||||
server_address = (r.get_host(False, self.flow), r.get_port(self.flow))
|
server_address = (r.host, r.port)
|
||||||
|
|
||||||
server = ServerConnection(server_address, None)
|
server = ServerConnection(server_address)
|
||||||
server.connect()
|
server.connect()
|
||||||
|
|
||||||
if server_ssl or r.get_scheme(self.flow) == "https":
|
if server_ssl or r.scheme == "https":
|
||||||
if self.config.http_form_out == "absolute": # form_out == absolute -> forward mode -> send CONNECT
|
if self.config.http_form_out == "absolute": # form_out == absolute -> forward mode -> send CONNECT
|
||||||
send_connect_request(server, r.get_host(), r.get_port())
|
send_connect_request(server, r.host, r.port)
|
||||||
r.form_out = "relative"
|
r.form_out = "relative"
|
||||||
server.establish_ssl(self.config.clientcerts,
|
server.establish_ssl(self.config.clientcerts, sni=r.host)
|
||||||
self.flow.server_conn.sni)
|
|
||||||
server.send(r._assemble())
|
server.send(r._assemble())
|
||||||
self.flow.response = HTTPResponse.from_stream(server.rfile, r.method,
|
self.flow.response = HTTPResponse.from_stream(server.rfile, r.method,
|
||||||
body_size_limit=self.config.body_size_limit)
|
body_size_limit=self.config.body_size_limit)
|
||||||
|
@ -58,7 +58,7 @@ class Flow(stateobject.SimpleStateObject):
|
|||||||
"""@type: ClientConnection"""
|
"""@type: ClientConnection"""
|
||||||
self.server_conn = server_conn
|
self.server_conn = server_conn
|
||||||
"""@type: ServerConnection"""
|
"""@type: ServerConnection"""
|
||||||
self.live = live # Used by flow.request.set_url to change the server address
|
self.live = live
|
||||||
"""@type: LiveConnection"""
|
"""@type: LiveConnection"""
|
||||||
|
|
||||||
self.error = None
|
self.error = None
|
||||||
|
@ -753,10 +753,10 @@ class TestRequest:
|
|||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
f = tutils.tflow()
|
f = tutils.tflow()
|
||||||
r = f.request
|
r = f.request
|
||||||
u = r.get_url(False, f)
|
u = r.url
|
||||||
assert r.set_url(u, f)
|
r.url = u
|
||||||
assert not r.set_url("", f)
|
tutils.raises(ValueError, setattr, r, "url", "")
|
||||||
assert r.get_url(False, f) == u
|
assert r.url == u
|
||||||
assert r._assemble()
|
assert r._assemble()
|
||||||
assert r.size() == len(r._assemble())
|
assert r.size() == len(r._assemble())
|
||||||
|
|
||||||
@ -771,83 +771,81 @@ class TestRequest:
|
|||||||
tutils.raises("Cannot assemble flow with CONTENT_MISSING", r._assemble)
|
tutils.raises("Cannot assemble flow with CONTENT_MISSING", r._assemble)
|
||||||
|
|
||||||
def test_get_url(self):
|
def test_get_url(self):
|
||||||
f = tutils.tflow()
|
r = tutils.treq()
|
||||||
r = f.request
|
|
||||||
|
|
||||||
assert r.get_url(False, f) == "http://address:22/path"
|
assert r.url == "http://address:22/path"
|
||||||
|
|
||||||
r.scheme = "https"
|
r.scheme = "https"
|
||||||
assert r.get_url(False, f) == "https://address:22/path"
|
assert r.url == "https://address:22/path"
|
||||||
|
|
||||||
r.host = "host"
|
r.host = "host"
|
||||||
r.port = 42
|
r.port = 42
|
||||||
assert r.get_url(False, f) == "https://host:42/path"
|
assert r.url == "https://host:42/path"
|
||||||
|
|
||||||
r.host = "address"
|
r.host = "address"
|
||||||
r.port = 22
|
r.port = 22
|
||||||
assert r.get_url(False, f) == "https://address:22/path"
|
assert r.url== "https://address:22/path"
|
||||||
|
|
||||||
assert r.get_url(True, f) == "https://address:22/path"
|
assert r.pretty_url(True) == "https://address:22/path"
|
||||||
r.headers["Host"] = ["foo.com"]
|
r.headers["Host"] = ["foo.com"]
|
||||||
assert r.get_url(False, f) == "https://address:22/path"
|
assert r.pretty_url(False) == "https://address:22/path"
|
||||||
assert r.get_url(True, f) == "https://foo.com:22/path"
|
assert r.pretty_url(True) == "https://foo.com:22/path"
|
||||||
|
|
||||||
def test_path_components(self):
|
def test_path_components(self):
|
||||||
f = tutils.tflow()
|
r = tutils.treq()
|
||||||
r = f.request
|
|
||||||
r.path = "/"
|
r.path = "/"
|
||||||
assert r.get_path_components(f) == []
|
assert r.path_components == []
|
||||||
r.path = "/foo/bar"
|
r.path = "/foo/bar"
|
||||||
assert r.get_path_components(f) == ["foo", "bar"]
|
assert r.path_components == ["foo", "bar"]
|
||||||
q = flow.ODict()
|
q = flow.ODict()
|
||||||
q["test"] = ["123"]
|
q["test"] = ["123"]
|
||||||
r.set_query(q, f)
|
r.query = q
|
||||||
assert r.get_path_components(f) == ["foo", "bar"]
|
assert r.path_components == ["foo", "bar"]
|
||||||
|
|
||||||
r.set_path_components([], f)
|
r.path_components = []
|
||||||
assert r.get_path_components(f) == []
|
assert r.path_components == []
|
||||||
r.set_path_components(["foo"], f)
|
r.path_components = ["foo"]
|
||||||
assert r.get_path_components(f) == ["foo"]
|
assert r.path_components == ["foo"]
|
||||||
r.set_path_components(["/oo"], f)
|
r.path_components = ["/oo"]
|
||||||
assert r.get_path_components(f) == ["/oo"]
|
assert r.path_components == ["/oo"]
|
||||||
assert "%2F" in r.path
|
assert "%2F" in r.path
|
||||||
|
|
||||||
def test_getset_form_urlencoded(self):
|
def test_getset_form_urlencoded(self):
|
||||||
d = flow.ODict([("one", "two"), ("three", "four")])
|
d = flow.ODict([("one", "two"), ("three", "four")])
|
||||||
r = tutils.treq(content=utils.urlencode(d.lst))
|
r = tutils.treq(content=utils.urlencode(d.lst))
|
||||||
r.headers["content-type"] = [protocol.http.HDR_FORM_URLENCODED]
|
r.headers["content-type"] = [protocol.http.HDR_FORM_URLENCODED]
|
||||||
assert r.get_form_urlencoded() == d
|
assert r.form_urlencoded == d
|
||||||
|
|
||||||
d = flow.ODict([("x", "y")])
|
d = flow.ODict([("x", "y")])
|
||||||
r.set_form_urlencoded(d)
|
r.form_urlencoded = d
|
||||||
assert r.get_form_urlencoded() == d
|
assert r.form_urlencoded == d
|
||||||
|
|
||||||
r.headers["content-type"] = ["foo"]
|
r.headers["content-type"] = ["foo"]
|
||||||
assert not r.get_form_urlencoded()
|
assert not r.form_urlencoded
|
||||||
|
|
||||||
def test_getset_query(self):
|
def test_getset_query(self):
|
||||||
h = flow.ODictCaseless()
|
h = flow.ODictCaseless()
|
||||||
|
|
||||||
f = tutils.tflow()
|
r = tutils.treq()
|
||||||
f.request.path = "/foo?x=y&a=b"
|
r.path = "/foo?x=y&a=b"
|
||||||
q = f.request.get_query(f)
|
q = r.query
|
||||||
assert q.lst == [("x", "y"), ("a", "b")]
|
assert q.lst == [("x", "y"), ("a", "b")]
|
||||||
|
|
||||||
f.request.path = "/"
|
r.path = "/"
|
||||||
q = f.request.get_query(f)
|
q = r.query
|
||||||
assert not q
|
assert not q
|
||||||
|
|
||||||
f.request.path = "/?adsfa"
|
r.path = "/?adsfa"
|
||||||
q = f.request.get_query(f)
|
q = r.query
|
||||||
assert q.lst == [("adsfa", "")]
|
assert q.lst == [("adsfa", "")]
|
||||||
|
|
||||||
f.request.path = "/foo?x=y&a=b"
|
r.path = "/foo?x=y&a=b"
|
||||||
assert f.request.get_query(f)
|
assert r.query
|
||||||
f.request.set_query(flow.ODict([]), f)
|
r.query = flow.ODict([])
|
||||||
assert not f.request.get_query(f)
|
assert not r.query
|
||||||
qv = flow.ODict([("a", "b"), ("c", "d")])
|
qv = flow.ODict([("a", "b"), ("c", "d")])
|
||||||
f.request.set_query(qv, f)
|
r.query = qv
|
||||||
assert f.request.get_query(f) == qv
|
assert r.query == qv
|
||||||
|
|
||||||
def test_anticache(self):
|
def test_anticache(self):
|
||||||
h = flow.ODictCaseless()
|
h = flow.ODictCaseless()
|
||||||
@ -918,14 +916,14 @@ class TestRequest:
|
|||||||
h = flow.ODictCaseless()
|
h = flow.ODictCaseless()
|
||||||
r = tutils.treq()
|
r = tutils.treq()
|
||||||
r.headers = h
|
r.headers = h
|
||||||
assert r.get_cookies() is None
|
assert r.cookies is None
|
||||||
|
|
||||||
def test_get_cookies_single(self):
|
def test_get_cookies_single(self):
|
||||||
h = flow.ODictCaseless()
|
h = flow.ODictCaseless()
|
||||||
h["Cookie"] = ["cookiename=cookievalue"]
|
h["Cookie"] = ["cookiename=cookievalue"]
|
||||||
r = tutils.treq()
|
r = tutils.treq()
|
||||||
r.headers = h
|
r.headers = h
|
||||||
result = r.get_cookies()
|
result = r.cookies
|
||||||
assert len(result)==1
|
assert len(result)==1
|
||||||
assert result['cookiename']==('cookievalue',{})
|
assert result['cookiename']==('cookievalue',{})
|
||||||
|
|
||||||
@ -934,7 +932,7 @@ class TestRequest:
|
|||||||
h["Cookie"] = ["cookiename=cookievalue;othercookiename=othercookievalue"]
|
h["Cookie"] = ["cookiename=cookievalue;othercookiename=othercookievalue"]
|
||||||
r = tutils.treq()
|
r = tutils.treq()
|
||||||
r.headers = h
|
r.headers = h
|
||||||
result = r.get_cookies()
|
result = r.cookies
|
||||||
assert len(result)==2
|
assert len(result)==2
|
||||||
assert result['cookiename']==('cookievalue',{})
|
assert result['cookiename']==('cookievalue',{})
|
||||||
assert result['othercookiename']==('othercookievalue',{})
|
assert result['othercookiename']==('othercookievalue',{})
|
||||||
@ -944,7 +942,7 @@ class TestRequest:
|
|||||||
h["Cookie"] = ["cookiename=coo=kievalue;othercookiename=othercookievalue"]
|
h["Cookie"] = ["cookiename=coo=kievalue;othercookiename=othercookievalue"]
|
||||||
r = tutils.treq()
|
r = tutils.treq()
|
||||||
r.headers = h
|
r.headers = h
|
||||||
result = r.get_cookies()
|
result = r.cookies
|
||||||
assert len(result)==2
|
assert len(result)==2
|
||||||
assert result['cookiename']==('coo=kievalue',{})
|
assert result['cookiename']==('coo=kievalue',{})
|
||||||
assert result['othercookiename']==('othercookievalue',{})
|
assert result['othercookiename']==('othercookievalue',{})
|
||||||
@ -1054,14 +1052,14 @@ class TestResponse:
|
|||||||
h = flow.ODictCaseless()
|
h = flow.ODictCaseless()
|
||||||
resp = tutils.tresp()
|
resp = tutils.tresp()
|
||||||
resp.headers = h
|
resp.headers = h
|
||||||
assert not resp.get_cookies()
|
assert not resp.cookies
|
||||||
|
|
||||||
def test_get_cookies_simple(self):
|
def test_get_cookies_simple(self):
|
||||||
h = flow.ODictCaseless()
|
h = flow.ODictCaseless()
|
||||||
h["Set-Cookie"] = ["cookiename=cookievalue"]
|
h["Set-Cookie"] = ["cookiename=cookievalue"]
|
||||||
resp = tutils.tresp()
|
resp = tutils.tresp()
|
||||||
resp.headers = h
|
resp.headers = h
|
||||||
result = resp.get_cookies()
|
result = resp.cookies
|
||||||
assert len(result)==1
|
assert len(result)==1
|
||||||
assert "cookiename" in result
|
assert "cookiename" in result
|
||||||
assert result["cookiename"] == ("cookievalue", {})
|
assert result["cookiename"] == ("cookievalue", {})
|
||||||
@ -1071,7 +1069,7 @@ class TestResponse:
|
|||||||
h["Set-Cookie"] = ["cookiename=cookievalue;domain=example.com;expires=Wed Oct 21 16:29:41 2015;path=/; HttpOnly"]
|
h["Set-Cookie"] = ["cookiename=cookievalue;domain=example.com;expires=Wed Oct 21 16:29:41 2015;path=/; HttpOnly"]
|
||||||
resp = tutils.tresp()
|
resp = tutils.tresp()
|
||||||
resp.headers = h
|
resp.headers = h
|
||||||
result = resp.get_cookies()
|
result = resp.cookies
|
||||||
assert len(result)==1
|
assert len(result)==1
|
||||||
assert "cookiename" in result
|
assert "cookiename" in result
|
||||||
assert result["cookiename"][0] == "cookievalue"
|
assert result["cookiename"][0] == "cookievalue"
|
||||||
@ -1086,7 +1084,7 @@ class TestResponse:
|
|||||||
h["Set-Cookie"] = ["cookiename=; Expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/"]
|
h["Set-Cookie"] = ["cookiename=; Expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/"]
|
||||||
resp = tutils.tresp()
|
resp = tutils.tresp()
|
||||||
resp.headers = h
|
resp.headers = h
|
||||||
result = resp.get_cookies()
|
result = resp.cookies
|
||||||
assert len(result)==1
|
assert len(result)==1
|
||||||
assert "cookiename" in result
|
assert "cookiename" in result
|
||||||
assert result["cookiename"][0] == ""
|
assert result["cookiename"][0] == ""
|
||||||
@ -1097,7 +1095,7 @@ class TestResponse:
|
|||||||
h["Set-Cookie"] = ["cookiename=cookievalue","othercookie=othervalue"]
|
h["Set-Cookie"] = ["cookiename=cookievalue","othercookie=othervalue"]
|
||||||
resp = tutils.tresp()
|
resp = tutils.tresp()
|
||||||
resp.headers = h
|
resp.headers = h
|
||||||
result = resp.get_cookies()
|
result = resp.cookies
|
||||||
assert len(result)==2
|
assert len(result)==2
|
||||||
assert "cookiename" in result
|
assert "cookiename" in result
|
||||||
assert result["cookiename"] == ("cookievalue", {})
|
assert result["cookiename"] == ("cookievalue", {})
|
||||||
|
@ -58,12 +58,12 @@ class TestHTTPRequest:
|
|||||||
tutils.raises("Invalid request form", r._assemble, "antiauthority")
|
tutils.raises("Invalid request form", r._assemble, "antiauthority")
|
||||||
|
|
||||||
def test_set_url(self):
|
def test_set_url(self):
|
||||||
f = tutils.tflow(req=tutils.treq_absolute())
|
r = tutils.treq_absolute()
|
||||||
f.request.set_url("https://otheraddress:42/ORLY", f)
|
r.url = "https://otheraddress:42/ORLY"
|
||||||
assert f.request.scheme == "https"
|
assert r.scheme == "https"
|
||||||
assert f.request.host == "otheraddress"
|
assert r.host == "otheraddress"
|
||||||
assert f.request.port == 42
|
assert r.port == 42
|
||||||
assert f.request.path == "/ORLY"
|
assert r.path == "/ORLY"
|
||||||
|
|
||||||
|
|
||||||
class TestHTTPResponse:
|
class TestHTTPResponse:
|
||||||
|
@ -23,7 +23,7 @@ class TestServerConnection:
|
|||||||
self.d.shutdown()
|
self.d.shutdown()
|
||||||
|
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
sc = ServerConnection((self.d.IFACE, self.d.port), None)
|
sc = ServerConnection((self.d.IFACE, self.d.port))
|
||||||
sc.connect()
|
sc.connect()
|
||||||
f = tutils.tflow()
|
f = tutils.tflow()
|
||||||
f.server_conn = sc
|
f.server_conn = sc
|
||||||
@ -35,7 +35,7 @@ class TestServerConnection:
|
|||||||
sc.finish()
|
sc.finish()
|
||||||
|
|
||||||
def test_terminate_error(self):
|
def test_terminate_error(self):
|
||||||
sc = ServerConnection((self.d.IFACE, self.d.port), None)
|
sc = ServerConnection((self.d.IFACE, self.d.port))
|
||||||
sc.connect()
|
sc.connect()
|
||||||
sc.connection = mock.Mock()
|
sc.connection = mock.Mock()
|
||||||
sc.connection.recv = mock.Mock(return_value=False)
|
sc.connection.recv = mock.Mock(return_value=False)
|
||||||
|
@ -337,17 +337,14 @@ class MasterRedirectRequest(tservers.TestMaster):
|
|||||||
def handle_request(self, f):
|
def handle_request(self, f):
|
||||||
request = f.request
|
request = f.request
|
||||||
if request.path == "/p/201":
|
if request.path == "/p/201":
|
||||||
url = request.get_url(False, f)
|
url = request.url
|
||||||
new = "http://127.0.0.1:%s/p/201" % self.redirect_port
|
new = "http://127.0.0.1:%s/p/201" % self.redirect_port
|
||||||
|
|
||||||
request.set_url(new, f)
|
request.url = new
|
||||||
request.set_url(new, f)
|
|
||||||
f.live.change_server(("127.0.0.1", self.redirect_port), False)
|
f.live.change_server(("127.0.0.1", self.redirect_port), False)
|
||||||
request.set_url(url, f)
|
request.url = url
|
||||||
tutils.raises("SSL handshake error", f.live.change_server, ("127.0.0.1", self.redirect_port), True)
|
tutils.raises("SSL handshake error", f.live.change_server, ("127.0.0.1", self.redirect_port), True)
|
||||||
request.set_url(new, f)
|
request.url = new
|
||||||
request.set_url(url, f)
|
|
||||||
request.set_url(new, f)
|
|
||||||
tservers.TestMaster.handle_request(self, f)
|
tservers.TestMaster.handle_request(self, f)
|
||||||
|
|
||||||
def handle_response(self, f):
|
def handle_response(self, f):
|
||||||
|
Loading…
Reference in New Issue
Block a user