import os import mysql.connector from mysql.connector import pooling from flask import Flask, jsonify, request from flask_cors import CORS from datetime import datetime # --- 從環境變數讀取資料庫連線資訊 --- # os.environ.get() 會嘗試讀取環境變數,如果找不到,則使用後面的預設值 # 這讓程式碼在本地 (使用預設值) 和 Zeabur (使用環境變數) 都能運作 DB_CONFIG = { 'user': os.environ.get('DB_USER', 'A023'), 'password': os.environ.get('DB_PASSWORD', 'UkrHhx76kCCM'), 'host': os.environ.get('DB_HOST', 'mysql.theaken.com'), 'port': int(os.environ.get('DB_PORT', 33306)), 'database': os.environ.get('DB_NAME', 'db_A023'), } # --- 建立應用程式與啟用 CORS --- app = Flask(__name__) CORS(app) # --- 建立資料庫連線池 --- connection_pool = None try: connection_pool = mysql.connector.pooling.MySQLConnectionPool( pool_name="api_pool", pool_size=5, **DB_CONFIG ) print("資料庫連線池建立成功!") except mysql.connector.Error as err: print(f"資料庫連線池建立失敗: {err}") # --- 統一回應格式的輔助函式 --- def create_response(status, data, message, code): return jsonify({ "status": status, "code": code, "message": message, "data": data }), code def create_error_response(message, code): return create_response("error", None, message, code) # --- API Endpoint: /menu --- @app.route('/menu', methods=['GET']) def get_menu_by_date(): menu_date_str = request.args.get('date') if not menu_date_str: return create_error_response("The 'date' parameter is required.", 400) try: datetime.strptime(menu_date_str, '%Y-%m-%d') except ValueError: return create_error_response("Invalid date format. Please use YYYY-MM-DD.", 400) if not connection_pool: return create_error_response("Database connection not available.", 503) conn = None cursor = None try: conn = connection_pool.get_connection() cursor = conn.cursor(dictionary=True) query = ("SELECT main_course, side_dish, addon " "FROM menu_items WHERE menu_date = %s") cursor.execute(query, (menu_date_str,)) menu_items = cursor.fetchall() if not menu_items: return create_response("success", [], "no menu found", 200) return create_response("success", menu_items, "Menu retrieved successfully.", 200) except mysql.connector.Error as err: return create_error_response(f"Database error: {err}", 500) except Exception as e: return create_error_response(f"An unexpected error occurred: {e}", 500) finally: if cursor: cursor.close() if conn and conn.is_connected(): conn.close() # --- 全域錯誤處理 --- @app.errorhandler(404) def not_found(error): return create_error_response("Resource not found.", 404) @app.errorhandler(405) def method_not_allowed(error): return create_error_response("Method not allowed.", 405) # --- 啟動應用程式 --- if __name__ == '__main__': # Zeabur 會透過 Gunicorn 啟動,這段主要用於本地測試 # Zeabur 會自動注入 PORT 環境變數 port = int(os.environ.get('PORT', 5000)) app.run(host='0.0.0.0', port=port, debug=False) # 正式環境 debug 應為 False