mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2025-02-01 07:49:10 +00:00
More robust response handling.
This commit is contained in:
parent
86fe199988
commit
7a49cdfef3
@ -40,23 +40,23 @@ class Pathoc(tcp.TCPClient):
|
||||
r = rparse.parse_request({}, i)
|
||||
req = r.serve(self.wfile)
|
||||
if reqdump:
|
||||
print >> fp, ">>", req["method"], req["path"]
|
||||
print >> fp, "\n>>", req["method"], req["path"]
|
||||
for a in req["actions"]:
|
||||
print >> fp, "\t",
|
||||
for x in a:
|
||||
print x,
|
||||
print
|
||||
print >> fp, x,
|
||||
print >> fp
|
||||
self.wfile.flush()
|
||||
resp = self.request(i)
|
||||
resp = http.read_response(self.rfile, r.method, None)
|
||||
except rparse.ParseException, v:
|
||||
print >> fp, "Error parsing request spec: %s"%v.msg
|
||||
print >> fp, v.marked()
|
||||
return
|
||||
except http.HttpError, v:
|
||||
print >> fp, v.msg
|
||||
print >> fp, "<<", v.msg
|
||||
return
|
||||
except tcp.NetLibTimeout:
|
||||
print >> fp, "Timeout"
|
||||
print >> fp, "<<", "Timeout"
|
||||
else:
|
||||
if respdump:
|
||||
print_full(fp, *resp)
|
||||
|
@ -18,6 +18,82 @@ class PathodHandler(tcp.BaseHandler):
|
||||
def handle_sni(self, connection):
|
||||
self.sni = connection.get_servername()
|
||||
|
||||
def handle_request(self):
|
||||
"""
|
||||
Returns True if handling should continue.
|
||||
"""
|
||||
line = self.rfile.readline()
|
||||
if line == "\r\n" or line == "\n": # Possible leftover from previous message
|
||||
line = self.rfile.readline()
|
||||
if line == "":
|
||||
return
|
||||
|
||||
parts = http.parse_init_http(line)
|
||||
if not parts:
|
||||
s = "Invalid first line: %s"%line.rstrip()
|
||||
self.info(s)
|
||||
self.server.add_log(
|
||||
dict(
|
||||
type = "error",
|
||||
msg = s
|
||||
)
|
||||
)
|
||||
return
|
||||
method, path, httpversion = parts
|
||||
|
||||
headers = http.read_headers(self.rfile)
|
||||
content = http.read_http_body_request(
|
||||
self.rfile, self.wfile, headers, httpversion, None
|
||||
)
|
||||
|
||||
crafted = None
|
||||
for i in self.server.anchors:
|
||||
if i[0].match(path):
|
||||
crafted = i[1]
|
||||
|
||||
if not crafted and path.startswith(self.server.prefix):
|
||||
spec = urllib.unquote(path)[len(self.server.prefix):]
|
||||
try:
|
||||
crafted = rparse.parse_response(self.server.request_settings, spec)
|
||||
except rparse.ParseException, v:
|
||||
crafted = rparse.InternalResponse(
|
||||
800,
|
||||
"Error parsing response spec: %s\n"%v.msg + v.marked()
|
||||
)
|
||||
|
||||
request_log = dict(
|
||||
path = path,
|
||||
method = method,
|
||||
headers = headers.lst,
|
||||
sni = self.sni,
|
||||
remote_address = self.client_address,
|
||||
httpversion = httpversion,
|
||||
)
|
||||
if crafted:
|
||||
response_log = crafted.serve(self.wfile)
|
||||
if response_log["disconnect"]:
|
||||
return
|
||||
self.server.add_log(
|
||||
dict(
|
||||
type = "crafted",
|
||||
request=request_log,
|
||||
response=response_log
|
||||
)
|
||||
)
|
||||
else:
|
||||
cc = wsgi.ClientConn(self.client_address)
|
||||
req = wsgi.Request(cc, "http", method, path, headers, content)
|
||||
sn = self.connection.getsockname()
|
||||
app = wsgi.WSGIAdaptor(
|
||||
self.server.app,
|
||||
sn[0],
|
||||
self.server.port,
|
||||
version.NAMEVERSION
|
||||
)
|
||||
app.serve(req, self.wfile)
|
||||
self.debug("%s %s"%(method, path))
|
||||
return True
|
||||
|
||||
def handle(self):
|
||||
if self.server.ssloptions:
|
||||
try:
|
||||
@ -34,79 +110,21 @@ class PathodHandler(tcp.BaseHandler):
|
||||
)
|
||||
)
|
||||
self.info(s)
|
||||
self.finish()
|
||||
return
|
||||
|
||||
while not self.finished:
|
||||
line = self.rfile.readline()
|
||||
if line == "\r\n" or line == "\n": # Possible leftover from previous message
|
||||
line = self.rfile.readline()
|
||||
if line == "":
|
||||
return None
|
||||
|
||||
parts = http.parse_init_http(line)
|
||||
if not parts:
|
||||
s = "Invalid first line: %s"%line.rstrip()
|
||||
self.info(s)
|
||||
try:
|
||||
if not self.handle_request():
|
||||
return
|
||||
except tcp.NetLibDisconnect:
|
||||
self.info("Disconnect")
|
||||
self.server.add_log(
|
||||
dict(
|
||||
type = "error",
|
||||
msg = s
|
||||
msg = "Disconnect"
|
||||
)
|
||||
)
|
||||
return None
|
||||
method, path, httpversion = parts
|
||||
|
||||
headers = http.read_headers(self.rfile)
|
||||
content = http.read_http_body_request(
|
||||
self.rfile, self.wfile, headers, httpversion, None
|
||||
)
|
||||
|
||||
crafted = None
|
||||
for i in self.server.anchors:
|
||||
if i[0].match(path):
|
||||
crafted = i[1]
|
||||
|
||||
if not crafted and path.startswith(self.server.prefix):
|
||||
spec = urllib.unquote(path)[len(self.server.prefix):]
|
||||
try:
|
||||
crafted = rparse.parse_response(self.server.request_settings, spec)
|
||||
except rparse.ParseException, v:
|
||||
crafted = rparse.InternalResponse(
|
||||
800,
|
||||
"Error parsing response spec: %s\n"%v.msg + v.marked()
|
||||
)
|
||||
|
||||
request_log = dict(
|
||||
path = path,
|
||||
method = method,
|
||||
headers = headers.lst,
|
||||
sni = self.sni,
|
||||
remote_address = self.client_address,
|
||||
httpversion = httpversion,
|
||||
)
|
||||
if crafted:
|
||||
response_log = crafted.serve(self.wfile)
|
||||
if response_log["disconnect"]:
|
||||
self.finish()
|
||||
self.server.add_log(
|
||||
dict(
|
||||
type = "crafted",
|
||||
request=request_log,
|
||||
response=response_log
|
||||
)
|
||||
)
|
||||
else:
|
||||
cc = wsgi.ClientConn(self.client_address)
|
||||
req = wsgi.Request(cc, "http", method, path, headers, content)
|
||||
sn = self.connection.getsockname()
|
||||
app = wsgi.WSGIAdaptor(
|
||||
self.server.app,
|
||||
sn[0],
|
||||
self.server.port,
|
||||
version.NAMEVERSION
|
||||
)
|
||||
app.serve(req, self.wfile)
|
||||
self.debug("%s %s"%(method, path))
|
||||
return
|
||||
|
||||
|
||||
class Pathod(tcp.TCPServer):
|
||||
|
@ -64,11 +64,13 @@ class _DaemonTests:
|
||||
scheme = "https" if self.SSL else "http"
|
||||
return requests.get("%s://localhost:%s/p/%s"%(scheme, self.d.port, spec), verify=False)
|
||||
|
||||
def pathoc(self, spec):
|
||||
def pathoc(self, spec, timeout=None):
|
||||
c = pathoc.Pathoc("localhost", self.d.port)
|
||||
c.connect()
|
||||
if self.SSL:
|
||||
c.convert_to_ssl()
|
||||
if timeout:
|
||||
c.settimeout(timeout)
|
||||
return c.request(spec)
|
||||
|
||||
def test_preline(self):
|
||||
@ -114,6 +116,7 @@ class _DaemonTests:
|
||||
assert "foo" in l["msg"]
|
||||
|
||||
|
||||
|
||||
class TestDaemon(_DaemonTests):
|
||||
SSL = False
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user