jen900704 commited on
Commit
9b6f854
·
verified ·
1 Parent(s): edc7b9c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -23
app.py CHANGED
@@ -1,7 +1,9 @@
1
  import sys
2
  import os
3
  from werkzeug.serving import run_simple
 
4
  sys.path.append(os.path.dirname(os.path.abspath(__file__)))
 
5
  from dotenv import load_dotenv
6
 
7
  load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), ".env"))
@@ -10,8 +12,8 @@ from flask import Flask, send_from_directory
10
  from flask_cors import CORS
11
  from constants import Constants
12
  from api.api_blueprint import api_blueprint
13
- from models.base import db
14
- from models.combined_labels import CombinedLabels
15
 
16
  import logging
17
 
@@ -31,37 +33,47 @@ def create_app():
31
  create_session_dir()
32
 
33
  # --- 2. 靜態檔:dist/ ---
 
 
34
  app = Flask(__name__, static_folder="dist", static_url_path="")
35
 
36
- # 🔴 3. 最重要:API 一律掛在 `/api`,不要再用 BASE_PATH ---
37
- # 不要:url_prefix=f"{Constants.BASE_PATH}/api"
38
  app.register_blueprint(api_blueprint, url_prefix="/api")
39
 
40
- # --- 4. React / Vite build 的入口(index.html) ---
41
- @app.route("/")
42
- def serve_index():
43
- # 這裡會讀 dist/index.html
44
- return send_from_directory("dist", "index.html")
45
-
46
- @app.route("/<path:path>")
47
- def serve_static(path):
48
- # 這裡會 serve dist 裡其餘 js / css / wasm 等
49
- return send_from_directory("dist", path)
50
-
51
- # --- 5. (選配)簡單 health check,方便你測試 /api 有沒有活著 ---
52
  @app.route("/api/ping")
53
  def ping():
54
  return {"status": "ok"}
55
 
56
- # 過濾 progress 噪音 log
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  class FilterProgressRequests(logging.Filter):
58
  def filter(self, record):
59
  return "/api/progress/" not in record.getMessage()
60
 
61
  logging.getLogger("werkzeug").addFilter(FilterProgressRequests())
 
 
62
  CORS(app)
63
 
64
- # SharedArrayBuffer 相關 header
65
  @app.after_request
66
  def add_security_headers(response):
67
  response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
@@ -75,23 +87,25 @@ def create_app():
75
  app = create_app()
76
 
77
 
78
- # --- 6. 本機開發 (可選) ---
79
  def find_watch_files():
80
- watch_dirs = ['api', 'models', 'services']
81
  base_path = os.path.dirname(__file__)
82
  all_files = []
83
  for d in watch_dirs:
84
  dir_path = os.path.join(base_path, d)
85
  for root, _, files in os.walk(dir_path):
86
  for f in files:
87
- if f.endswith('.py'):
88
  all_files.append(os.path.join(root, f))
89
  return all_files
90
 
91
 
92
  if __name__ == "__main__":
93
  use_ssl = os.environ.get("USE_SSL", "false").lower() == "true"
94
- ssl_context = ("../certs/localhost-cert.pem", "../certs/localhost-key.pem") if use_ssl else None
 
 
95
  run_simple(
96
  hostname="0.0.0.0",
97
  port=5001,
@@ -99,5 +113,5 @@ if __name__ == "__main__":
99
  use_debugger=True,
100
  use_reloader=True,
101
  extra_files=find_watch_files(),
102
- ssl_context=ssl_context
103
  )
 
1
  import sys
2
  import os
3
  from werkzeug.serving import run_simple
4
+
5
  sys.path.append(os.path.dirname(os.path.abspath(__file__)))
6
+
7
  from dotenv import load_dotenv
8
 
9
  load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), ".env"))
 
12
  from flask_cors import CORS
13
  from constants import Constants
14
  from api.api_blueprint import api_blueprint
15
+ from models.base import db # 保留原本 import(即使現在沒用到)
16
+ from models.combined_labels import CombinedLabels # 同上
17
 
18
  import logging
19
 
 
33
  create_session_dir()
34
 
35
  # --- 2. 靜態檔:dist/ ---
36
+ # static_folder 指向 Vite build 出來的 dist
37
+ # static_url_path 設成 "",讓 /assets/... 之類的路徑正確
38
  app = Flask(__name__, static_folder="dist", static_url_path="")
39
 
40
+ # --- 3. API 一律掛在 /api ---
 
41
  app.register_blueprint(api_blueprint, url_prefix="/api")
42
 
43
+ # --- 4. 簡單 health check ---
 
 
 
 
 
 
 
 
 
 
 
44
  @app.route("/api/ping")
45
  def ping():
46
  return {"status": "ok"}
47
 
48
+ # --- 5. React / Vite SPA:所有非靜態路徑 fallback 到 index.html ---
49
+ @app.route("/", defaults={"path": ""})
50
+ @app.route("/<path:path>")
51
+ def serve_spa(path: str):
52
+ """
53
+ 1. 如果 dist 裡真的有這個檔案,就當成靜態檔案回傳
54
+ 2. 如果沒有,就回 dist/index.html,交給 React Router 處理
55
+ 例如 /case/PanTS_00009391 這種 route
56
+ """
57
+ # 先嘗試當成靜態檔
58
+ if path:
59
+ full_path = os.path.join(app.static_folder, path)
60
+ if os.path.isfile(full_path):
61
+ return send_from_directory(app.static_folder, path)
62
+
63
+ # 找不到對應實體檔案 → 交給前端路由
64
+ return send_from_directory(app.static_folder, "index.html")
65
+
66
+ # --- 6. Log 過濾:不要一直印 /api/progress ---
67
  class FilterProgressRequests(logging.Filter):
68
  def filter(self, record):
69
  return "/api/progress/" not in record.getMessage()
70
 
71
  logging.getLogger("werkzeug").addFilter(FilterProgressRequests())
72
+
73
+ # --- 7. CORS ---
74
  CORS(app)
75
 
76
+ # --- 8. SharedArrayBuffer / WebGL 相關 header ---
77
  @app.after_request
78
  def add_security_headers(response):
79
  response.headers["Cross-Origin-Opener-Policy"] = "same-origin"
 
87
  app = create_app()
88
 
89
 
90
+ # --- 9. 本機開發可選 ---
91
  def find_watch_files():
92
+ watch_dirs = ["api", "models", "services"]
93
  base_path = os.path.dirname(__file__)
94
  all_files = []
95
  for d in watch_dirs:
96
  dir_path = os.path.join(base_path, d)
97
  for root, _, files in os.walk(dir_path):
98
  for f in files:
99
+ if f.endswith(".py"):
100
  all_files.append(os.path.join(root, f))
101
  return all_files
102
 
103
 
104
  if __name__ == "__main__":
105
  use_ssl = os.environ.get("USE_SSL", "false").lower() == "true"
106
+ ssl_context = (
107
+ ("../certs/localhost-cert.pem", "../certs/localhost-key.pem") if use_ssl else None
108
+ )
109
  run_simple(
110
  hostname="0.0.0.0",
111
  port=5001,
 
113
  use_debugger=True,
114
  use_reloader=True,
115
  extra_files=find_watch_files(),
116
+ ssl_context=ssl_context,
117
  )