Initial commit
This commit is contained in:
104
app.py
Normal file
104
app.py
Normal file
@@ -0,0 +1,104 @@
|
||||
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
|
Reference in New Issue
Block a user