Skip to content

Commit ec26fde

Browse files
committed
Merge remote-tracking branch 'origin/main' into dev/lalitm/ui
2 parents e7e9b08 + 6ce93b6 commit ec26fde

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed

infra/gae-internal/.gcloudignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# This file specifies files that are *not* uploaded to Google Cloud
2+
# using gcloud. It follows the same syntax as .gitignore, with the addition of
3+
# "#!include" directives (which insert the entries of the given .gitignore-style
4+
# file at that point).
5+
#
6+
# For more information, run:
7+
# $ gcloud topic gcloudignore
8+
#
9+
.gcloudignore
10+
# If you would like to upload your .git directory, .gitignore file or files
11+
# from your .gitignore file, remove the corresponding line
12+
# below:
13+
.git
14+
.gitignore
15+
16+
# Python pycache:
17+
__pycache__/
18+
# Ignored by the build system
19+
/setup.cfg

infra/gae-internal/app.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
runtime: python312
2+
3+
entrypoint: gunicorn -b :$PORT main:app
4+
5+
instance_class: F1
6+
7+
automatic_scaling:
8+
max_instances: 2

infra/gae-internal/deploy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
gcloud app deploy app.yaml --project google.com:perfetto-gae-internal
3+

infra/gae-internal/main.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import posixpath
2+
3+
from flask import Flask, Response, abort
4+
from flask_cors import CORS
5+
from google.cloud import storage
6+
7+
app = Flask(__name__)
8+
CORS(
9+
app,
10+
origins=["https://ui.perfetto.dev", "http://localhost:10000"],
11+
supports_credentials=True)
12+
13+
BUCKET_NAME = "perfetto-ui-internal"
14+
BASE_PREFIX = "extension-server-v1"
15+
16+
gcs_client = storage.Client()
17+
bucket = gcs_client.bucket(BUCKET_NAME)
18+
19+
20+
@app.route("/", defaults={"path": ""})
21+
@app.route("/<path:path>")
22+
def serve(path):
23+
# Normalize and reject any path traversal attempts.
24+
normalized = posixpath.normpath(path) if path else ""
25+
if normalized.startswith(
26+
"..") or "/../" in normalized or normalized.startswith("/"):
27+
abort(403)
28+
29+
blob_path = f"{BASE_PREFIX}/{normalized}" if normalized else BASE_PREFIX + "/"
30+
31+
blob = bucket.blob(blob_path)
32+
if not blob.exists():
33+
abort(404)
34+
35+
data = blob.download_as_bytes()
36+
content_type = blob.content_type or "application/octet-stream"
37+
return Response(data, content_type=content_type)
38+
39+
40+
if __name__ == "__main__":
41+
app.run(host="127.0.0.1", port=8080)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Flask==3.0.0
2+
Flask-Cors==4.0.0
3+
google-cloud-storage==2.14.0
4+
gunicorn==21.2.0

0 commit comments

Comments
 (0)