summaryrefslogtreecommitdiffstats
path: root/python/mozbuild/mozbuild/html_build_viewer.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/mozbuild/mozbuild/html_build_viewer.py')
-rw-r--r--python/mozbuild/mozbuild/html_build_viewer.py118
1 files changed, 118 insertions, 0 deletions
diff --git a/python/mozbuild/mozbuild/html_build_viewer.py b/python/mozbuild/mozbuild/html_build_viewer.py
new file mode 100644
index 0000000000..0582e6f1be
--- /dev/null
+++ b/python/mozbuild/mozbuild/html_build_viewer.py
@@ -0,0 +1,118 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This module contains code for running an HTTP server to view build info.
+import http.server
+import json
+import os
+
+import requests
+
+
+class HTTPHandler(http.server.BaseHTTPRequestHandler):
+ def do_GET(self):
+ s = self.server.wrapper
+ p = self.path
+
+ if p == "/build_resources.json":
+ self.send_response(200)
+ self.send_header("Content-Type", "application/json; charset=utf-8")
+ self.end_headers()
+
+ keys = sorted(s.json_files.keys())
+ s = json.dumps({"files": ["resources/%s" % k for k in keys]})
+ self.wfile.write(s.encode("utf-8"))
+ return
+
+ if p.startswith("/resources/"):
+ key = p[len("/resources/") :]
+
+ if key not in s.json_files:
+ self.send_error(404)
+ return
+
+ self.send_response(200)
+ self.send_header("Content-Type", "application/json; charset=utf-8")
+ self.end_headers()
+
+ self.wfile.write(s.json_files[key])
+ return
+
+ if p == "/":
+ p = "/build_resources.html"
+
+ self.serve_docroot(s.doc_root, p[1:])
+
+ def do_POST(self):
+ if self.path == "/shutdown":
+ self.server.wrapper.do_shutdown = True
+ self.send_response(200)
+ return
+
+ self.send_error(404)
+
+ def serve_docroot(self, root, path):
+ local_path = os.path.normpath(os.path.join(root, path))
+
+ # Cheap security. This doesn't resolve symlinks, etc. But, it should be
+ # acceptable since this server only runs locally.
+ if not local_path.startswith(root):
+ self.send_error(404)
+
+ if not os.path.exists(local_path):
+ self.send_error(404)
+ return
+
+ if os.path.isdir(local_path):
+ self.send_error(500)
+ return
+
+ self.send_response(200)
+ ct = "text/plain"
+ if path.endswith(".html"):
+ ct = "text/html"
+
+ self.send_header("Content-Type", ct)
+ self.end_headers()
+
+ with open(local_path, "rb") as fh:
+ self.wfile.write(fh.read())
+
+
+class BuildViewerServer(object):
+ def __init__(self, address="localhost", port=0):
+ # TODO use pkg_resources to obtain HTML resources.
+ pkg_dir = os.path.dirname(os.path.abspath(__file__))
+ doc_root = os.path.join(pkg_dir, "resources", "html-build-viewer")
+ assert os.path.isdir(doc_root)
+
+ self.doc_root = doc_root
+ self.json_files = {}
+
+ self.server = http.server.HTTPServer((address, port), HTTPHandler)
+ self.server.wrapper = self
+ self.do_shutdown = False
+
+ @property
+ def url(self):
+ hostname, port = self.server.server_address
+ return "http://%s:%d/" % (hostname, port)
+
+ def add_resource_json_file(self, key, path):
+ """Register a resource JSON file with the server.
+
+ The file will be made available under the name/key specified."""
+ with open(path, "rb") as fh:
+ self.json_files[key] = fh.read()
+
+ def add_resource_json_url(self, key, url):
+ """Register a resource JSON file at a URL."""
+ r = requests.get(url)
+ if r.status_code != 200:
+ raise Exception("Non-200 HTTP response code")
+ self.json_files[key] = r.text
+
+ def run(self):
+ while not self.do_shutdown:
+ self.server.handle_request()