From 5a6e22ad49510193a7f9c950e54abd32229fa7bf Mon Sep 17 00:00:00 2001 From: Lalit Maganti Date: Mon, 30 Mar 2026 12:50:51 +0000 Subject: [PATCH 1/3] ui: add gae internal server code This is the internal Google extension server. Very simple, just serving straight out of a GCS bucket. --- infra/gae-internal/.gcloudignore | 19 +++++++++++++++ infra/gae-internal/app.yaml | 8 +++++++ infra/gae-internal/deploy | 3 +++ infra/gae-internal/main.py | 37 +++++++++++++++++++++++++++++ infra/gae-internal/requirements.txt | 4 ++++ 5 files changed, 71 insertions(+) create mode 100644 infra/gae-internal/.gcloudignore create mode 100644 infra/gae-internal/app.yaml create mode 100755 infra/gae-internal/deploy create mode 100644 infra/gae-internal/main.py create mode 100644 infra/gae-internal/requirements.txt diff --git a/infra/gae-internal/.gcloudignore b/infra/gae-internal/.gcloudignore new file mode 100644 index 00000000000..603f0b6ea06 --- /dev/null +++ b/infra/gae-internal/.gcloudignore @@ -0,0 +1,19 @@ +# This file specifies files that are *not* uploaded to Google Cloud +# using gcloud. It follows the same syntax as .gitignore, with the addition of +# "#!include" directives (which insert the entries of the given .gitignore-style +# file at that point). +# +# For more information, run: +# $ gcloud topic gcloudignore +# +.gcloudignore +# If you would like to upload your .git directory, .gitignore file or files +# from your .gitignore file, remove the corresponding line +# below: +.git +.gitignore + +# Python pycache: +__pycache__/ +# Ignored by the build system +/setup.cfg \ No newline at end of file diff --git a/infra/gae-internal/app.yaml b/infra/gae-internal/app.yaml new file mode 100644 index 00000000000..f00aff916c3 --- /dev/null +++ b/infra/gae-internal/app.yaml @@ -0,0 +1,8 @@ +runtime: python312 + +entrypoint: gunicorn -b :$PORT main:app + +instance_class: F1 + +automatic_scaling: + max_instances: 2 diff --git a/infra/gae-internal/deploy b/infra/gae-internal/deploy new file mode 100755 index 00000000000..8a7bb47b3b1 --- /dev/null +++ b/infra/gae-internal/deploy @@ -0,0 +1,3 @@ +#!/bin/bash +gcloud app deploy app.yaml --project google.com:perfetto-gae-internal + diff --git a/infra/gae-internal/main.py b/infra/gae-internal/main.py new file mode 100644 index 00000000000..20f3a38407f --- /dev/null +++ b/infra/gae-internal/main.py @@ -0,0 +1,37 @@ +import posixpath + +from flask import Flask, Response, abort +from flask_cors import CORS +from google.cloud import storage + +app = Flask(__name__) +CORS(app, origins=["https://ui.perfetto.dev", "http://localhost:10000"], supports_credentials=True) + +BUCKET_NAME = "perfetto-ui-internal" +BASE_PREFIX = "extension-server-v1" + +gcs_client = storage.Client() +bucket = gcs_client.bucket(BUCKET_NAME) + + +@app.route("/", defaults={"path": ""}) +@app.route("/") +def serve(path): + # Normalize and reject any path traversal attempts. + normalized = posixpath.normpath(path) if path else "" + if normalized.startswith("..") or "/../" in normalized or normalized.startswith("/"): + abort(403) + + blob_path = f"{BASE_PREFIX}/{normalized}" if normalized else BASE_PREFIX + "/" + + blob = bucket.blob(blob_path) + if not blob.exists(): + abort(404) + + data = blob.download_as_bytes() + content_type = blob.content_type or "application/octet-stream" + return Response(data, content_type=content_type) + + +if __name__ == "__main__": + app.run(host="127.0.0.1", port=8080, debug=True) diff --git a/infra/gae-internal/requirements.txt b/infra/gae-internal/requirements.txt new file mode 100644 index 00000000000..60dd206376e --- /dev/null +++ b/infra/gae-internal/requirements.txt @@ -0,0 +1,4 @@ +Flask==3.0.0 +Flask-Cors==4.0.0 +google-cloud-storage==2.14.0 +gunicorn==21.2.0 From 2bba609a490702dcd2722dfab3cce3c9b9459c01 Mon Sep 17 00:00:00 2001 From: Lalit Maganti Date: Mon, 30 Mar 2026 12:56:42 +0000 Subject: [PATCH 2/3] Fix --- infra/gae-internal/main.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/infra/gae-internal/main.py b/infra/gae-internal/main.py index 20f3a38407f..a0ab779a221 100644 --- a/infra/gae-internal/main.py +++ b/infra/gae-internal/main.py @@ -5,7 +5,10 @@ from google.cloud import storage app = Flask(__name__) -CORS(app, origins=["https://ui.perfetto.dev", "http://localhost:10000"], supports_credentials=True) +CORS( + app, + origins=["https://ui.perfetto.dev", "http://localhost:10000"], + supports_credentials=True) BUCKET_NAME = "perfetto-ui-internal" BASE_PREFIX = "extension-server-v1" @@ -17,21 +20,22 @@ @app.route("/", defaults={"path": ""}) @app.route("/") def serve(path): - # Normalize and reject any path traversal attempts. - normalized = posixpath.normpath(path) if path else "" - if normalized.startswith("..") or "/../" in normalized or normalized.startswith("/"): - abort(403) + # Normalize and reject any path traversal attempts. + normalized = posixpath.normpath(path) if path else "" + if normalized.startswith( + "..") or "/../" in normalized or normalized.startswith("/"): + abort(403) - blob_path = f"{BASE_PREFIX}/{normalized}" if normalized else BASE_PREFIX + "/" + blob_path = f"{BASE_PREFIX}/{normalized}" if normalized else BASE_PREFIX + "/" - blob = bucket.blob(blob_path) - if not blob.exists(): - abort(404) + blob = bucket.blob(blob_path) + if not blob.exists(): + abort(404) - data = blob.download_as_bytes() - content_type = blob.content_type or "application/octet-stream" - return Response(data, content_type=content_type) + data = blob.download_as_bytes() + content_type = blob.content_type or "application/octet-stream" + return Response(data, content_type=content_type) if __name__ == "__main__": - app.run(host="127.0.0.1", port=8080, debug=True) + app.run(host="127.0.0.1", port=8080, debug=True) From cc664899e4fbdccb43067e7a7d4ecf49ac234bce Mon Sep 17 00:00:00 2001 From: Lalit Maganti Date: Mon, 30 Mar 2026 12:57:39 +0000 Subject: [PATCH 3/3] Fix --- infra/gae-internal/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/gae-internal/main.py b/infra/gae-internal/main.py index a0ab779a221..96cd9f2e4c6 100644 --- a/infra/gae-internal/main.py +++ b/infra/gae-internal/main.py @@ -38,4 +38,4 @@ def serve(path): if __name__ == "__main__": - app.run(host="127.0.0.1", port=8080, debug=True) + app.run(host="127.0.0.1", port=8080)