mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-10-26 17:21:58 -06:00
Fix SPA routing in Flask production
This commit is contained in:
@@ -336,9 +336,27 @@ from job_scheduler import set_credential_fetcher as scheduler_set_credential_fet
|
||||
# =============================================================================
|
||||
# Configure Flask, reverse-proxy awareness, CORS, and Socket.IO transport.
|
||||
|
||||
_STATIC_CANDIDATES = [
|
||||
os.path.join(os.path.dirname(__file__), '../web-interface/build'),
|
||||
os.path.join(os.path.dirname(__file__), 'WebUI/build'),
|
||||
os.path.join(os.path.dirname(__file__), '../WebUI/build'),
|
||||
]
|
||||
|
||||
_resolved_static_folder = None
|
||||
for candidate in _STATIC_CANDIDATES:
|
||||
absolute_candidate = os.path.abspath(candidate)
|
||||
if os.path.isdir(absolute_candidate):
|
||||
_resolved_static_folder = absolute_candidate
|
||||
break
|
||||
|
||||
if not _resolved_static_folder:
|
||||
# Fall back to the first candidate so Flask still initialises; individual
|
||||
# requests will 404 until a build exists, matching the previous behaviour.
|
||||
_resolved_static_folder = os.path.abspath(_STATIC_CANDIDATES[0])
|
||||
|
||||
app = Flask(
|
||||
__name__,
|
||||
static_folder=os.path.join(os.path.dirname(__file__), '../web-interface/build'),
|
||||
static_folder=_resolved_static_folder,
|
||||
static_url_path=''
|
||||
)
|
||||
|
||||
@@ -395,6 +413,34 @@ def serve_dist(path):
|
||||
return send_from_directory(app.static_folder, 'index.html')
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def spa_fallback(error):
|
||||
"""Serve the SPA entry point for unknown front-end routes.
|
||||
|
||||
When the browser refreshes on a client-side route (e.g. ``/devices``),
|
||||
Flask would normally raise a 404 because no matching server route exists.
|
||||
We intercept that here and return ``index.html`` so the React router can
|
||||
take over. API and asset paths continue to surface their original 404s.
|
||||
"""
|
||||
|
||||
# Preserve 404s for API endpoints, websocket upgrades, and obvious asset
|
||||
# requests (anything containing an extension).
|
||||
request_path = (request.path or '').strip()
|
||||
if request_path.startswith('/api') or request_path.startswith('/socket.io'):
|
||||
return error
|
||||
if '.' in os.path.basename(request_path):
|
||||
return error
|
||||
if request.method not in {'GET', 'HEAD'}:
|
||||
return error
|
||||
|
||||
try:
|
||||
return send_from_directory(app.static_folder, 'index.html')
|
||||
except Exception:
|
||||
# If the build is missing we fall back to the original 404 response so
|
||||
# the caller still receives an accurate status code.
|
||||
return error
|
||||
|
||||
|
||||
# Endpoint: /health — liveness probe for orchestrators.
|
||||
|
||||
@app.route("/health")
|
||||
|
||||
Reference in New Issue
Block a user