|
12 | 12 | from .pathsim_utils import make_pathsim_model |
13 | 13 | from pathsim.blocks import Scope |
14 | 14 |
|
15 | | -app = Flask(__name__) |
16 | | -CORS( |
17 | | - app, |
18 | | - resources={r"/*": {"origins": "http://localhost:5173"}}, |
19 | | - supports_credentials=True, |
20 | | -) |
| 15 | +# Configure Flask app for Cloud Run |
| 16 | +app = Flask(__name__, static_folder="../dist", static_url_path="") |
| 17 | + |
| 18 | +# Configure CORS based on environment |
| 19 | +if os.getenv("FLASK_ENV") == "production": |
| 20 | + # Production: Allow Cloud Run domains and common domains |
| 21 | + CORS( |
| 22 | + app, |
| 23 | + resources={ |
| 24 | + r"/*": { |
| 25 | + "origins": ["*"], # Allow all origins for Cloud Run |
| 26 | + "methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"], |
| 27 | + "allow_headers": ["Content-Type", "Authorization"], |
| 28 | + } |
| 29 | + }, |
| 30 | + ) |
| 31 | +else: |
| 32 | + # Development: Only allow localhost |
| 33 | + CORS( |
| 34 | + app, |
| 35 | + resources={ |
| 36 | + r"/*": {"origins": ["http://localhost:5173", "http://localhost:3000"]} |
| 37 | + }, |
| 38 | + supports_credentials=True, |
| 39 | + ) |
21 | 40 |
|
22 | 41 |
|
23 | 42 | # Creates directory for saved graphs |
24 | 43 | SAVE_DIR = "saved_graphs" |
25 | 44 | os.makedirs(SAVE_DIR, exist_ok=True) |
26 | 45 |
|
27 | 46 |
|
28 | | -# Health check endpoint for CI/CD |
29 | | -@app.route("/", methods=["GET"]) |
| 47 | +# Serve React frontend for production |
| 48 | +@app.route("/") |
| 49 | +def serve_frontend(): |
| 50 | + """Serve the React frontend in production.""" |
| 51 | + if os.getenv("FLASK_ENV") == "production": |
| 52 | + return app.send_static_file("index.html") |
| 53 | + else: |
| 54 | + return jsonify({"message": "Fuel Cycle Simulator API", "status": "running"}) |
| 55 | + |
| 56 | + |
| 57 | +# Health check endpoint for Cloud Run |
30 | 58 | @app.route("/health", methods=["GET"]) |
31 | 59 | def health_check(): |
32 | 60 | return jsonify( |
@@ -184,5 +212,16 @@ def run_pathsim(): |
184 | 212 | return jsonify({"success": False, "error": f"Server error: {str(e)}"}), 500 |
185 | 213 |
|
186 | 214 |
|
| 215 | +# Catch-all route for React Router (SPA routing) |
| 216 | +@app.route("/<path:path>") |
| 217 | +def catch_all(path): |
| 218 | + """Serve React app for all routes in production (for client-side routing).""" |
| 219 | + if os.getenv("FLASK_ENV") == "production": |
| 220 | + return app.send_static_file("index.html") |
| 221 | + else: |
| 222 | + return jsonify({"error": "Route not found"}), 404 |
| 223 | + |
| 224 | + |
187 | 225 | if __name__ == "__main__": |
188 | | - app.run(port=8000, debug=True) |
| 226 | + port = int(os.getenv("PORT", 8000)) |
| 227 | + app.run(host="0.0.0.0", port=port, debug=os.getenv("FLASK_ENV") != "production") |
0 commit comments