mitmproxy/mitmproxy/export.py
2017-02-18 00:13:14 +01:00

189 lines
5.0 KiB
Python

import io
import json
import pprint
import re
import textwrap
from typing import Any
from mitmproxy import http
def _native(s):
if isinstance(s, bytes):
return s.decode()
return s
def dictstr(items, indent: str) -> str:
lines = []
for k, v in items:
lines.append(indent + "%s: %s,\n" % (repr(_native(k)), repr(_native(v))))
return "{\n%s}\n" % "".join(lines)
def curl_command(flow: http.HTTPFlow) -> str:
data = "curl "
request = flow.request.copy()
request.decode(strict=False)
for k, v in request.headers.items(multi=True):
data += "-H '%s:%s' " % (k, v)
if request.method != "GET":
data += "-X %s " % request.method
data += "'%s'" % request.url
if request.content:
data += " --data-binary '%s'" % _native(request.content)
return data
def python_arg(arg: str, val: Any) -> str:
if not val:
return ""
if arg:
arg += "="
arg_str = "{}{},\n".format(
arg,
pprint.pformat(val, 79 - len(arg))
)
return textwrap.indent(arg_str, " " * 4)
def python_code(flow: http.HTTPFlow):
code = io.StringIO()
def writearg(arg, val):
code.write(python_arg(arg, val))
code.write("import requests\n")
code.write("\n")
if flow.request.method.lower() in ("get", "post", "put", "head", "delete", "patch"):
code.write("response = requests.{}(\n".format(flow.request.method.lower()))
else:
code.write("response = requests.request(\n")
writearg("", flow.request.method)
url_without_query = flow.request.url.split("?", 1)[0]
writearg("", url_without_query)
writearg("params", list(flow.request.query.fields))
headers = flow.request.headers.copy()
# requests adds those by default.
for x in (":authority", "host", "content-length"):
headers.pop(x, None)
writearg("headers", dict(headers))
try:
if "json" not in flow.request.headers.get("content-type", ""):
raise ValueError()
writearg("json", json.loads(flow.request.text))
except ValueError:
writearg("data", flow.request.content)
code.seek(code.tell() - 2) # remove last comma
code.write("\n)\n")
code.write("\n")
code.write("print(response.text)")
return code.getvalue()
def locust_code(flow):
code = textwrap.dedent("""
from locust import HttpLocust, TaskSet, task
class UserBehavior(TaskSet):
def on_start(self):
''' on_start is called when a Locust start before any task is scheduled '''
self.{name}()
@task()
def {name}(self):
url = self.locust.host + '{path}'
{headers}{params}{data}
self.response = self.client.request(
method='{method}',
url=url,{args}
)
### Additional tasks can go here ###
class WebsiteUser(HttpLocust):
task_set = UserBehavior
min_wait = 1000
max_wait = 3000
""").strip()
name = re.sub('\W|^(?=\d)', '_', flow.request.path.strip("/").split("?", 1)[0])
if not name:
new_name = "_".join([str(flow.request.host), str(flow.request.timestamp_start)])
name = re.sub('\W|^(?=\d)', '_', new_name)
path_without_query = flow.request.path.split("?")[0]
args = ""
headers = ""
if flow.request.headers:
lines = [
(_native(k), _native(v)) for k, v in flow.request.headers.fields
if _native(k).lower() not in [":authority", "host", "cookie"]
]
lines = [" '%s': '%s',\n" % (k, v) for k, v in lines]
headers += "\n headers = {\n%s }\n" % "".join(lines)
args += "\n headers=headers,"
params = ""
if flow.request.query:
lines = [
" %s: %s,\n" % (repr(k), repr(v))
for k, v in
flow.request.query.collect()
]
params = "\n params = {\n%s }\n" % "".join(lines)
args += "\n params=params,"
data = ""
if flow.request.content:
data = "\n data = '''%s'''\n" % _native(flow.request.content)
args += "\n data=data,"
code = code.format(
name=name,
path=path_without_query,
headers=headers,
params=params,
data=data,
method=flow.request.method,
args=args,
)
return code
def locust_task(flow):
code = locust_code(flow)
start_task = len(code.split('@task')[0]) - 4
end_task = -19 - len(code.split('### Additional')[1])
task_code = code[start_task:end_task]
return task_code
def url(flow):
return flow.request.url
EXPORTERS = [
("content", "c", None),
("headers+content", "h", None),
("url", "u", url),
("as curl command", "r", curl_command),
("as python code", "p", python_code),
("as locust code", "l", locust_code),
("as locust task", "t", locust_task),
]