
With this fix in place the script mitm-serve-app-dev.sh works as advertised. It proxies the https prod server and even allows login. It is fairly slow though compared to run-server.sh, so it cannot fully replace it at this point. Note that there is also a WIP Change I0ff7e314a for getting us from mitmproxy 2.0.2 to 4.0.4. Change-Id: Id79510228d6e701f724cc947146768fabae58457
170 lines
7.4 KiB
Python
170 lines
7.4 KiB
Python
# 1. install and setup mitmproxy v2.0.2: https://mitmproxy.readthedocs.io/en/v2.0.2/install.html
|
|
# (In case of python versions trouble, use https://www.anaconda.com/)
|
|
# 2. mitmdump -q -s -p 8888 \
|
|
# "serve-app-dev.py --app /path/to/polygerrit-ui/app/"
|
|
# 3. start Chrome with --proxy-server="127.0.0.1:8888" --user-data-dir=/tmp/devchrome
|
|
# 4. open, say, gerrit-review.googlesource.com. Or chromium-review.googlesource.com. Any.
|
|
# 5. uncompiled source files are served and you can log in, too.
|
|
# 6. enjoy!
|
|
#
|
|
# P.S. For replacing plugins, use --plugins or --plugin_root
|
|
#
|
|
# --plugin takes comma-separated list of plugins to add or replace.
|
|
#
|
|
# Example: Adding a new plugin to the server response:
|
|
# --plugins ~/gerrit-testsite/plugins/myplugin.html
|
|
#
|
|
# Example: Replace all matching plugins with local versions:
|
|
# --plugins ~/gerrit-testsite/plugins/
|
|
# Following files will be served if they exist for /plugins/tricium/static/tricium.html:
|
|
# ~/gerrit-testsite/plugins/tricium.html
|
|
# ~/gerrit-testsite/plugins/tricium/static/tricium.html
|
|
#
|
|
# --assets takes assets bundle.html, expecting rest of the assets files to be in the same folder
|
|
#
|
|
# Example:
|
|
# --assets ~/gerrit-testsite/assets/a3be19f.html
|
|
#
|
|
|
|
from mitmproxy import http
|
|
from mitmproxy.script import concurrent
|
|
import argparse
|
|
import json
|
|
import mimetypes
|
|
import os.path
|
|
import re
|
|
import zipfile
|
|
|
|
class Server:
|
|
def __init__(self, devpath, components, plugins, pluginroot, assets, strip_assets, theme):
|
|
if devpath:
|
|
print("Serving app from " + devpath)
|
|
if components:
|
|
print("Serving components from " + components)
|
|
if pluginroot:
|
|
print("Serving plugins from " + pluginroot)
|
|
if assets:
|
|
self.assets_root, self.assets_file = os.path.split(assets)
|
|
print("Assets: using " + self.assets_file + " from " + self.assets_root)
|
|
else:
|
|
self.assets_root = None
|
|
if plugins:
|
|
self.plugins = {path.split("/")[-1:][0]: path for path in map(expandpath, plugins.split(","))}
|
|
for filename, path in self.plugins.items():
|
|
print("Serving " + filename + " from " + path)
|
|
else:
|
|
self.plugins = {}
|
|
self.devpath = devpath
|
|
self.components = components
|
|
self.pluginroot = pluginroot
|
|
self.strip_assets = strip_assets
|
|
self.theme = theme
|
|
|
|
def readfile(self, path):
|
|
with open(path, 'rb') as contentfile:
|
|
return contentfile.read()
|
|
|
|
@concurrent
|
|
def response(flow: http.HTTPFlow) -> None:
|
|
if server.strip_assets:
|
|
assets_bundle = 'googlesource.com/polygerrit_assets'
|
|
assets_pos = flow.response.text.find(assets_bundle)
|
|
if assets_pos != -1:
|
|
t = flow.response.text
|
|
flow.response.text = t[:t.rfind('<', 0, assets_pos)] + t[t.find('>', assets_pos) + 1:]
|
|
return
|
|
|
|
if server.assets_root:
|
|
marker = 'webcomponents-lite.js"></script>'
|
|
pos = flow.response.text.find(marker)
|
|
if pos != -1:
|
|
pos += len(marker)
|
|
flow.response.text = ''.join([
|
|
flow.response.text[:pos],
|
|
'<link rel="import" href="/gerrit_assets/123.0/' + server.assets_file + '">',
|
|
flow.response.text[pos:]
|
|
])
|
|
|
|
assets_prefix = "/gerrit_assets/123.0/"
|
|
if flow.request.path.startswith(assets_prefix):
|
|
assets_file = flow.request.path[len(assets_prefix):]
|
|
flow.response.content = server.readfile(server.assets_root + '/' + assets_file)
|
|
flow.response.status_code = 200
|
|
if assets_file.endswith('.js'):
|
|
flow.response.headers['Content-type'] = 'text/javascript'
|
|
return
|
|
m = re.match(".+polygerrit_ui/\d+\.\d+/(.+)", flow.request.path)
|
|
pluginmatch = re.match("^/plugins/(.+)", flow.request.path)
|
|
localfile = ""
|
|
content = ""
|
|
if flow.request.path == "/config/server/info":
|
|
config = json.loads(flow.response.content[5:].decode('utf8'))
|
|
if server.theme:
|
|
config['default_theme'] = '/static/gerrit-theme.html'
|
|
for filename, path in server.plugins.items():
|
|
pluginname = filename.split(".")[0]
|
|
payload = config["plugin"]["js_resource_paths" if filename.endswith(".js") else "html_resource_paths"]
|
|
if list(filter(lambda url: filename in url, payload)):
|
|
continue
|
|
payload.append("plugins/" + pluginname + "/static/" + filename)
|
|
flow.response.content = str.encode(")]}'\n" + json.dumps(config))
|
|
if m is not None:
|
|
filepath = m.groups()[0]
|
|
if (filepath.startswith("bower_components/")):
|
|
with zipfile.ZipFile(server.components + "test_components.zip") as bower_zip:
|
|
content = bower_zip.read(filepath)
|
|
localfile = server.devpath + filepath
|
|
elif pluginmatch is not None:
|
|
pluginfile = flow.request.path_components[-1]
|
|
if server.plugins and pluginfile in server.plugins:
|
|
if os.path.isfile(server.plugins[pluginfile]):
|
|
localfile = server.plugins[pluginfile]
|
|
else:
|
|
print("Can't find file " + server.plugins[pluginfile] + " for " + flow.request.path)
|
|
elif server.pluginroot:
|
|
pluginurl = pluginmatch.groups()[0]
|
|
if os.path.isfile(server.pluginroot + pluginfile):
|
|
localfile = server.pluginroot + pluginfile
|
|
elif os.path.isfile(server.pluginroot + pluginurl):
|
|
localfile = server.pluginroot + pluginurl
|
|
|
|
if server.theme:
|
|
if flow.request.path.endswith('/gerrit-theme.html'):
|
|
localfile = server.theme
|
|
else:
|
|
match = re.match("^/static(/[\w\.]+)$", flow.request.path)
|
|
if match is not None:
|
|
localfile = os.path.dirname(server.theme) + match.group(1)
|
|
|
|
if localfile and os.path.isfile(localfile):
|
|
if pluginmatch is not None:
|
|
print("Serving " + flow.request.path + " from " + localfile)
|
|
content = server.readfile(localfile)
|
|
|
|
if content:
|
|
flow.response.content = content
|
|
flow.response.status_code = 200
|
|
localtype = mimetypes.guess_type(localfile)
|
|
if localtype and localtype[0]:
|
|
flow.response.headers['Content-type'] = localtype[0]
|
|
|
|
def expandpath(path):
|
|
return os.path.realpath(os.path.expanduser(path))
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--app", type=str, default="", help="Path to /polygerrit-ui/app/")
|
|
parser.add_argument("--components", type=str, default="", help="Path to test_components.zip")
|
|
parser.add_argument("--plugins", type=str, default="", help="Comma-separated list of plugin files to add/replace")
|
|
parser.add_argument("--plugin_root", type=str, default="", help="Path containing individual plugin files to replace")
|
|
parser.add_argument("--assets", type=str, default="", help="Path containing assets file to import.")
|
|
parser.add_argument("--strip_assets", action="store_true", help="Strip plugin bundles from the response.")
|
|
parser.add_argument("--theme", default="", type=str, help="Path to the default site theme to be used.")
|
|
args = parser.parse_args()
|
|
server = Server(expandpath(args.app) + '/',
|
|
expandpath(args.components) + '/',
|
|
args.plugins,
|
|
expandpath(args.plugin_root) + '/',
|
|
args.assets and expandpath(args.assets),
|
|
args.strip_assets,
|
|
expandpath(args.theme))
|