th commited on
Commit
76b1cf2
·
1 Parent(s): cf8055d

fix: 鉴权fail-closed + 44端点async→def + Dockerfile锁依赖commit

Browse files

安全: 移除硬编码默认key fallback(sisi_default_key_change_me)。
API_KEY/SISI_HF_API_KEY均未配置时启动记录error日志,所有受保护
端点返回503拒绝服务,不再接受可猜测的默认key。

性能: 44个async def端点全部改为def(FastAPI线程池)。全文件零await,
纯同步CPU计算跑在async def里会阻塞uvicorn事件循环,单worker下
并发请求互相卡死(与ziwei API同类问题,badbcb4)。

供应链: Dockerfile克隆china-testing/bazi锁定到commit 7150d5b
(2026-07-09 HEAD),上游变更/删库不再影响生产构建。

冒烟测试: 未配置key→503(任意key), 错误key→403, 正确key→200
(/api/qimen/now)。语法/导入均过。

🦊 Generated with Sisi

Files changed (2) hide show
  1. Dockerfile +4 -2
  2. app.py +59 -46
Dockerfile CHANGED
@@ -15,8 +15,10 @@ COPY requirements.txt .
15
  # Install Python dependencies
16
  RUN pip install --no-cache-dir -r requirements.txt
17
 
18
- # Clone the bazi library
19
- RUN git clone https://github.com/china-testing/bazi.git /app/bazi_lib
 
 
20
 
21
  # Copy all application code
22
  COPY *.py .
 
15
  # Install Python dependencies
16
  RUN pip install --no-cache-dir -r requirements.txt
17
 
18
+ # Clone the bazi library — pinned to a fixed commit (2026-07-09) so upstream
19
+ # changes/deletions can't silently alter or break our production builds
20
+ RUN git clone https://github.com/china-testing/bazi.git /app/bazi_lib \
21
+ && git -C /app/bazi_lib checkout 7150d5b6fba5e563dd0751b957dc990bb84ab6f0
22
 
23
  # Copy all application code
24
  COPY *.py .
app.py CHANGED
@@ -59,11 +59,24 @@ logger = logging.getLogger(__name__)
59
  # Support both naming conventions:
60
  # - API_KEY: For HuggingFace Space settings (simple, since only one API key)
61
  # - SISI_HF_API_KEY: For Cloudflare (clear distinction among many API keys)
62
- API_KEY = os.environ.get("API_KEY") or os.environ.get("SISI_HF_API_KEY") or "sisi_default_key_change_me"
 
 
 
 
 
 
 
 
63
 
64
 
65
  def verify_api_key(x_api_key: Optional[str] = Header(None)):
66
- """Verify API key from request header"""
 
 
 
 
 
67
  if x_api_key != API_KEY:
68
  raise HTTPException(
69
  status_code=403,
@@ -649,7 +662,7 @@ def health_check():
649
 
650
  @app.post("/calculate-bazi")
651
  @app.post("/api/calculate-bazi") # Alternative endpoint
652
- async def calculate_bazi(req: BaZiRequest, api_key: str = Depends(verify_api_key)):
653
  """
654
  Calculate BaZi (八字) chart from birth information
655
 
@@ -727,7 +740,7 @@ async def calculate_bazi(req: BaZiRequest, api_key: str = Depends(verify_api_key
727
 
728
 
729
  @app.post("/calculate-bazi-simple")
730
- async def calculate_bazi_simple(req: BaZiRequest, api_key: str = Depends(verify_api_key)):
731
  """
732
  Simplified BaZi calculation - returns only essential data
733
 
@@ -769,7 +782,7 @@ async def calculate_bazi_simple(req: BaZiRequest, api_key: str = Depends(verify_
769
 
770
  @app.post("/calculate-bazi-complete")
771
  @app.post("/api/calculate-bazi-complete") # Alternative endpoint
772
- async def calculate_bazi_complete(req: BaZiCompleteRequest, api_key: str = Depends(verify_api_key)):
773
  """
774
  Calculate complete BaZi with 大运 (Major Cycles) and 流年 (Yearly Cycles)
775
 
@@ -869,7 +882,7 @@ async def calculate_bazi_complete(req: BaZiCompleteRequest, api_key: str = Depen
869
 
870
  @app.post("/analyze-shensha")
871
  @app.post("/api/analyze-shensha") # Alternative endpoint
872
- async def analyze_shensha(req: BaZiRequest, api_key: str = Depends(verify_api_key)):
873
  """
874
  🔮 Analyze Spiritual Forces (神煞分析) - Advanced Feature
875
 
@@ -1026,7 +1039,7 @@ async def analyze_shensha(req: BaZiRequest, api_key: str = Depends(verify_api_ke
1026
 
1027
  @app.post("/analyze-genju")
1028
  @app.post("/api/analyze-genju") # Alternative endpoint
1029
- async def analyze_genju(req: BaZiRequest, api_key: str = Depends(verify_api_key)):
1030
  """
1031
  🎯 Analyze Life Pattern (格局分析) - Core Premium Feature
1032
 
@@ -1211,7 +1224,7 @@ async def analyze_genju(req: BaZiRequest, api_key: str = Depends(verify_api_key)
1211
 
1212
  @app.post("/analyze-dayun")
1213
  @app.post("/api/analyze-dayun") # Alternative endpoint
1214
- async def analyze_dayun(req: BaZiCompleteRequest, api_key: str = Depends(verify_api_key)):
1215
  """
1216
  📅 Analyze Major Cycles (大运分析) - Premium Fortune Prediction
1217
 
@@ -1472,7 +1485,7 @@ async def analyze_dayun(req: BaZiCompleteRequest, api_key: str = Depends(verify_
1472
 
1473
  @app.post("/ai-interpretation")
1474
  @app.post("/api/ai-interpretation") # Alternative endpoint
1475
- async def ai_interpretation(req: BaZiInterpretationRequest, api_key: str = Depends(verify_api_key)):
1476
  """
1477
  🤖 AI BaZi Interpretation - Transform Technical Analysis into Natural Language
1478
 
@@ -1751,7 +1764,7 @@ async def ai_interpretation(req: BaZiInterpretationRequest, api_key: str = Depen
1751
 
1752
  @app.post("/monthly-fortune")
1753
  @app.post("/api/monthly-fortune") # Alternative endpoint
1754
- async def analyze_monthly_fortune_api(req: MonthlyFortuneRequest, api_key: str = Depends(verify_api_key)):
1755
  """
1756
  📅 Monthly Fortune Analysis (流月运势分析)
1757
 
@@ -1828,7 +1841,7 @@ async def analyze_monthly_fortune_api(req: MonthlyFortuneRequest, api_key: str =
1828
 
1829
  @app.post("/career-monthly-fortune")
1830
  @app.post("/api/career-monthly-fortune") # Alternative endpoint
1831
- async def analyze_career_monthly_fortune_api(req: CareerMonthlyFortuneRequest, api_key: str = Depends(verify_api_key)):
1832
  """
1833
  💼 Career-Specific Monthly Fortune Analysis (事业月运分析)
1834
 
@@ -1898,7 +1911,7 @@ async def analyze_career_monthly_fortune_api(req: CareerMonthlyFortuneRequest, a
1898
 
1899
  @app.post("/yearly-fortune")
1900
  @app.post("/api/yearly-fortune") # Alternative endpoint
1901
- async def analyze_yearly_fortune_api(req: YearlyFortuneRequest, api_key: str = Depends(verify_api_key)):
1902
  """
1903
  🎯 Yearly Fortune Analysis - 12 Month Complete Forecast (流年12个月运势)
1904
 
@@ -2025,7 +2038,7 @@ async def analyze_yearly_fortune_api(req: YearlyFortuneRequest, api_key: str = D
2025
 
2026
  @app.post("/daily-fortune")
2027
  @app.post("/api/daily-fortune") # Alternative endpoint
2028
- async def analyze_daily_fortune_api(req: DailyFortuneRequest, api_key: str = Depends(verify_api_key)):
2029
  """
2030
  🗓️ Daily Fortune & Date Selection (流日择日分析)
2031
 
@@ -2103,7 +2116,7 @@ async def analyze_daily_fortune_api(req: DailyFortuneRequest, api_key: str = Dep
2103
 
2104
  @app.post("/hourly-fortune")
2105
  @app.post("/api/hourly-fortune") # Alternative endpoint
2106
- async def analyze_hourly_fortune_api(req: DailyFortuneRequest, api_key: str = Depends(verify_api_key)):
2107
  """
2108
  ⏰ Hourly Fortune Analysis (时辰吉凶分析)
2109
 
@@ -2179,7 +2192,7 @@ async def analyze_hourly_fortune_api(req: DailyFortuneRequest, api_key: str = De
2179
 
2180
  @app.post("/find-auspicious-dates")
2181
  @app.post("/api/find-auspicious-dates") # Alternative endpoint
2182
- async def find_auspicious_dates_api(req: FindAuspiciousDatesRequest, api_key: str = Depends(verify_api_key)):
2183
  """
2184
  🔍 Find Auspicious Dates (寻找吉日)
2185
 
@@ -2284,7 +2297,7 @@ async def find_auspicious_dates_api(req: FindAuspiciousDatesRequest, api_key: st
2284
  # ==================== Chinese Calendar API ====================
2285
 
2286
  @app.get("/api/calendar/today")
2287
- async def get_today_calendar():
2288
  """
2289
  Get today's Chinese lunar calendar information
2290
 
@@ -2346,7 +2359,7 @@ async def get_today_calendar():
2346
 
2347
 
2348
  @app.get("/api/calendar/range")
2349
- async def get_calendar_range(start: str, end: str):
2350
  """
2351
  Get Chinese lunar calendar information for a date range
2352
 
@@ -2408,7 +2421,7 @@ async def get_calendar_range(start: str, end: str):
2408
 
2409
 
2410
  @app.get("/api/calendar/{date_str}")
2411
- async def get_calendar_by_date(date_str: str):
2412
  """
2413
  Get Chinese lunar calendar information for a specific date
2414
 
@@ -2458,7 +2471,7 @@ class LunarToSolarRequest(BaseModel):
2458
 
2459
 
2460
  @app.post("/api/calendar/convert-lunar-to-solar")
2461
- async def convert_lunar_to_solar(request: LunarToSolarRequest):
2462
  """
2463
  Convert Chinese Lunar calendar date to Gregorian (Solar) calendar date
2464
 
@@ -2544,7 +2557,7 @@ class NineStarsRequest(BaseModel):
2544
 
2545
 
2546
  @app.post("/api/nine-stars/analyze")
2547
- async def analyze_nine_stars(
2548
  req: NineStarsRequest,
2549
  api_key: str = Depends(verify_api_key)
2550
  ):
@@ -2649,7 +2662,7 @@ async def analyze_nine_stars(
2649
 
2650
 
2651
  @app.get("/api/nine-stars/today")
2652
- async def get_today_nine_stars(
2653
  hour: int = 12,
2654
  api_key: str = Depends(verify_api_key)
2655
  ):
@@ -2693,7 +2706,7 @@ class Constellation28Request(BaseModel):
2693
 
2694
 
2695
  @app.post("/api/28-constellations/analyze")
2696
- async def analyze_28_constellations(
2697
  req: Constellation28Request,
2698
  api_key: str = Depends(verify_api_key)
2699
  ):
@@ -2796,7 +2809,7 @@ async def analyze_28_constellations(
2796
 
2797
 
2798
  @app.get("/api/28-constellations/today")
2799
- async def get_today_constellation(api_key: str = Depends(verify_api_key)):
2800
  """
2801
  ⭐ Get today's 28 Lunar Mansions constellation
2802
 
@@ -2829,7 +2842,7 @@ async def get_today_constellation(api_key: str = Depends(verify_api_key)):
2829
 
2830
 
2831
  @app.post("/api/28-constellations/find-auspicious")
2832
- async def find_auspicious_dates(
2833
  activity: str,
2834
  start_date: str,
2835
  end_date: str,
@@ -2921,7 +2934,7 @@ from zodiac_fortune_service import ZodiacFortuneService
2921
 
2922
 
2923
  @app.get("/api/zodiac-fortune/today/{zodiac}")
2924
- async def get_today_zodiac_fortune(zodiac: str):
2925
  """
2926
  🐉 Get today's fortune for a specific zodiac (今日生肖运程)
2927
 
@@ -2971,7 +2984,7 @@ async def get_today_zodiac_fortune(zodiac: str):
2971
 
2972
 
2973
  @app.get("/api/zodiac-fortune/{zodiac}/{date_str}")
2974
- async def get_zodiac_fortune_by_date(zodiac: str, date_str: str):
2975
  """
2976
  🐉 Get fortune for a specific zodiac on a specific date (指定日期生肖运程)
2977
 
@@ -3014,7 +3027,7 @@ async def get_zodiac_fortune_by_date(zodiac: str, date_str: str):
3014
 
3015
 
3016
  @app.get("/api/zodiac-fortune/all/{date_str}")
3017
- async def get_all_zodiac_fortune(date_str: str):
3018
  """
3019
  🐉 Get fortune for ALL 12 zodiacs on a specific date (12生肖运程)
3020
 
@@ -3117,7 +3130,7 @@ class MarriageCompatibilityRequest(BaseModel):
3117
 
3118
  @app.post("/api/marriage-compatibility")
3119
  @app.post("/marriage-compatibility")
3120
- async def analyze_marriage_compatibility(
3121
  req: MarriageCompatibilityRequest,
3122
  api_key: str = Depends(verify_api_key)
3123
  ):
@@ -3243,7 +3256,7 @@ class FortuneScoreRequest(BaseModel):
3243
 
3244
  @app.post("/api/fortune-score")
3245
  @app.post("/fortune-score")
3246
- async def calculate_comprehensive_fortune_score(
3247
  req: FortuneScoreRequest,
3248
  api_key: str = Depends(verify_api_key)
3249
  ):
@@ -3344,7 +3357,7 @@ class RitualRecommendRequest(BaseModel):
3344
 
3345
  @app.get("/rituals")
3346
  @app.get("/api/rituals") # 备用路由
3347
- async def get_all_rituals(api_key: str = Depends(verify_api_key)):
3348
  """
3349
  获取所有能量仪式
3350
 
@@ -3386,7 +3399,7 @@ async def get_all_rituals(api_key: str = Depends(verify_api_key)):
3386
 
3387
  @app.get("/rituals/{ritual_id}")
3388
  @app.get("/api/rituals/{ritual_id}") # 备用路由
3389
- async def get_ritual_by_id(ritual_id: str, api_key: str = Depends(verify_api_key)):
3390
  """
3391
  获取单个仪式详情
3392
 
@@ -3435,7 +3448,7 @@ async def get_ritual_by_id(ritual_id: str, api_key: str = Depends(verify_api_key
3435
 
3436
  @app.post("/rituals/search")
3437
  @app.post("/api/rituals/search") # 备用路由
3438
- async def search_rituals(request: RitualSearchRequest, api_key: str = Depends(verify_api_key)):
3439
  """
3440
  搜索仪式
3441
 
@@ -3505,7 +3518,7 @@ async def search_rituals(request: RitualSearchRequest, api_key: str = Depends(ve
3505
 
3506
  @app.get("/rituals/category/{category}")
3507
  @app.get("/api/rituals/category/{category}") # 备用路由
3508
- async def get_rituals_by_category(category: str, api_key: str = Depends(verify_api_key)):
3509
  """
3510
  按类别获取仪式
3511
 
@@ -3549,7 +3562,7 @@ async def get_rituals_by_category(category: str, api_key: str = Depends(verify_a
3549
 
3550
  @app.get("/rituals/moon-phase/current")
3551
  @app.get("/api/rituals/moon-phase/current") # 备用路由
3552
- async def get_current_moon_phase_rituals(api_key: str = Depends(verify_api_key)):
3553
  """
3554
  获取当前月相适合的仪式
3555
 
@@ -3587,7 +3600,7 @@ async def get_current_moon_phase_rituals(api_key: str = Depends(verify_api_key))
3587
 
3588
  @app.post("/rituals/recommend")
3589
  @app.post("/api/rituals/recommend") # 备用路由
3590
- async def recommend_rituals(request: RitualRecommendRequest, api_key: str = Depends(verify_api_key)):
3591
  """
3592
  个性化仪式推荐
3593
 
@@ -3652,7 +3665,7 @@ async def recommend_rituals(request: RitualRecommendRequest, api_key: str = Depe
3652
 
3653
  @app.get("/rituals/related/{ritual_id}")
3654
  @app.get("/api/rituals/related/{ritual_id}") # 备用路由
3655
- async def get_related_rituals(ritual_id: str, limit: int = 5, api_key: str = Depends(verify_api_key)):
3656
  """
3657
  获取相关仪式
3658
 
@@ -3697,7 +3710,7 @@ async def get_related_rituals(ritual_id: str, limit: int = 5, api_key: str = Dep
3697
 
3698
  @app.get("/rituals/statistics")
3699
  @app.get("/api/rituals/statistics") # 备用路由
3700
- async def get_rituals_statistics(api_key: str = Depends(verify_api_key)):
3701
  """
3702
  获取仪式统计信息
3703
 
@@ -3750,7 +3763,7 @@ class BodyReadingRequest(BaseModel):
3750
 
3751
  @app.post("/analyze-body-reading")
3752
  @app.post("/api/analyze-body-reading")
3753
- async def analyze_body_reading_endpoint(
3754
  req: BodyReadingRequest,
3755
  api_key: str = Depends(verify_api_key)
3756
  ):
@@ -3846,7 +3859,7 @@ class MarriageDestinyRequest(BaseModel):
3846
 
3847
  @app.post("/analyze-marriage-destiny")
3848
  @app.post("/api/analyze-marriage-destiny")
3849
- async def analyze_marriage_destiny(
3850
  req: MarriageDestinyRequest,
3851
  api_key: str = Depends(verify_api_key)
3852
  ):
@@ -3961,7 +3974,7 @@ class QimenChartRequest(BaseModel):
3961
 
3962
  @app.post("/api/qimen/chart")
3963
  @app.post("/qimen-chart")
3964
- async def calculate_qimen_chart(
3965
  req: QimenChartRequest,
3966
  api_key: str = Depends(verify_api_key)
3967
  ):
@@ -4022,7 +4035,7 @@ async def calculate_qimen_chart(
4022
 
4023
  @app.get("/api/qimen/now")
4024
  @app.get("/qimen-now")
4025
- async def get_qimen_now(
4026
  purpose: str = "综合",
4027
  api_key: str = Depends(verify_api_key)
4028
  ):
@@ -4089,7 +4102,7 @@ def _liuyao_response(coins, question, purpose) -> dict:
4089
 
4090
  @app.post("/api/liuyao/divine")
4091
  @app.post("/liuyao-divine")
4092
- async def divine_liuyao(
4093
  req: LiuYaoRequest,
4094
  api_key: str = Depends(verify_api_key)
4095
  ):
@@ -4110,7 +4123,7 @@ async def divine_liuyao(
4110
 
4111
  @app.get("/api/liuyao/now")
4112
  @app.get("/liuyao-now")
4113
- async def get_liuyao_now(
4114
  purpose: str = "综合",
4115
  question: str = "",
4116
  api_key: str = Depends(verify_api_key)
@@ -4144,7 +4157,7 @@ class FengshuiMingGuaRequest(BaseModel):
4144
 
4145
  @app.post("/api/fengshui/home-analysis")
4146
  @app.post("/fengshui-home-analysis")
4147
- async def fengshui_home_analysis(
4148
  req: FengshuiHomeRequest,
4149
  api_key: str = Depends(verify_api_key)
4150
  ):
@@ -4166,7 +4179,7 @@ async def fengshui_home_analysis(
4166
 
4167
  @app.post("/api/fengshui/ming-gua")
4168
  @app.post("/fengshui-ming-gua")
4169
- async def fengshui_ming_gua(
4170
  req: FengshuiMingGuaRequest,
4171
  api_key: str = Depends(verify_api_key)
4172
  ):
@@ -4181,7 +4194,7 @@ async def fengshui_ming_gua(
4181
 
4182
 
4183
  @app.get("/api/fengshui/zhai-gua/{facing}")
4184
- async def fengshui_zhai_gua(
4185
  facing: str,
4186
  api_key: str = Depends(verify_api_key)
4187
  ):
 
59
  # Support both naming conventions:
60
  # - API_KEY: For HuggingFace Space settings (simple, since only one API key)
61
  # - SISI_HF_API_KEY: For Cloudflare (clear distinction among many API keys)
62
+ # Fail closed: no hardcoded fallback — if neither env var is set, all
63
+ # protected endpoints refuse service instead of accepting a default key.
64
+ API_KEY = os.environ.get("API_KEY") or os.environ.get("SISI_HF_API_KEY")
65
+
66
+ if not API_KEY:
67
+ logger.error(
68
+ "🔒 API key is NOT configured (set API_KEY or SISI_HF_API_KEY). "
69
+ "All protected endpoints will return 503 until a key is set."
70
+ )
71
 
72
 
73
  def verify_api_key(x_api_key: Optional[str] = Header(None)):
74
+ """Verify API key from request header (fail closed when unconfigured)"""
75
+ if not API_KEY:
76
+ raise HTTPException(
77
+ status_code=503,
78
+ detail="🔒 API key is not configured on the server. Service unavailable."
79
+ )
80
  if x_api_key != API_KEY:
81
  raise HTTPException(
82
  status_code=403,
 
662
 
663
  @app.post("/calculate-bazi")
664
  @app.post("/api/calculate-bazi") # Alternative endpoint
665
+ def calculate_bazi(req: BaZiRequest, api_key: str = Depends(verify_api_key)):
666
  """
667
  Calculate BaZi (八字) chart from birth information
668
 
 
740
 
741
 
742
  @app.post("/calculate-bazi-simple")
743
+ def calculate_bazi_simple(req: BaZiRequest, api_key: str = Depends(verify_api_key)):
744
  """
745
  Simplified BaZi calculation - returns only essential data
746
 
 
782
 
783
  @app.post("/calculate-bazi-complete")
784
  @app.post("/api/calculate-bazi-complete") # Alternative endpoint
785
+ def calculate_bazi_complete(req: BaZiCompleteRequest, api_key: str = Depends(verify_api_key)):
786
  """
787
  Calculate complete BaZi with 大运 (Major Cycles) and 流年 (Yearly Cycles)
788
 
 
882
 
883
  @app.post("/analyze-shensha")
884
  @app.post("/api/analyze-shensha") # Alternative endpoint
885
+ def analyze_shensha(req: BaZiRequest, api_key: str = Depends(verify_api_key)):
886
  """
887
  🔮 Analyze Spiritual Forces (神煞分析) - Advanced Feature
888
 
 
1039
 
1040
  @app.post("/analyze-genju")
1041
  @app.post("/api/analyze-genju") # Alternative endpoint
1042
+ def analyze_genju(req: BaZiRequest, api_key: str = Depends(verify_api_key)):
1043
  """
1044
  🎯 Analyze Life Pattern (格局分析) - Core Premium Feature
1045
 
 
1224
 
1225
  @app.post("/analyze-dayun")
1226
  @app.post("/api/analyze-dayun") # Alternative endpoint
1227
+ def analyze_dayun(req: BaZiCompleteRequest, api_key: str = Depends(verify_api_key)):
1228
  """
1229
  📅 Analyze Major Cycles (大运分析) - Premium Fortune Prediction
1230
 
 
1485
 
1486
  @app.post("/ai-interpretation")
1487
  @app.post("/api/ai-interpretation") # Alternative endpoint
1488
+ def ai_interpretation(req: BaZiInterpretationRequest, api_key: str = Depends(verify_api_key)):
1489
  """
1490
  🤖 AI BaZi Interpretation - Transform Technical Analysis into Natural Language
1491
 
 
1764
 
1765
  @app.post("/monthly-fortune")
1766
  @app.post("/api/monthly-fortune") # Alternative endpoint
1767
+ def analyze_monthly_fortune_api(req: MonthlyFortuneRequest, api_key: str = Depends(verify_api_key)):
1768
  """
1769
  📅 Monthly Fortune Analysis (流月运势分析)
1770
 
 
1841
 
1842
  @app.post("/career-monthly-fortune")
1843
  @app.post("/api/career-monthly-fortune") # Alternative endpoint
1844
+ def analyze_career_monthly_fortune_api(req: CareerMonthlyFortuneRequest, api_key: str = Depends(verify_api_key)):
1845
  """
1846
  💼 Career-Specific Monthly Fortune Analysis (事业月运分析)
1847
 
 
1911
 
1912
  @app.post("/yearly-fortune")
1913
  @app.post("/api/yearly-fortune") # Alternative endpoint
1914
+ def analyze_yearly_fortune_api(req: YearlyFortuneRequest, api_key: str = Depends(verify_api_key)):
1915
  """
1916
  🎯 Yearly Fortune Analysis - 12 Month Complete Forecast (流年12个月运势)
1917
 
 
2038
 
2039
  @app.post("/daily-fortune")
2040
  @app.post("/api/daily-fortune") # Alternative endpoint
2041
+ def analyze_daily_fortune_api(req: DailyFortuneRequest, api_key: str = Depends(verify_api_key)):
2042
  """
2043
  🗓️ Daily Fortune & Date Selection (流日择日分析)
2044
 
 
2116
 
2117
  @app.post("/hourly-fortune")
2118
  @app.post("/api/hourly-fortune") # Alternative endpoint
2119
+ def analyze_hourly_fortune_api(req: DailyFortuneRequest, api_key: str = Depends(verify_api_key)):
2120
  """
2121
  ⏰ Hourly Fortune Analysis (时辰吉凶分析)
2122
 
 
2192
 
2193
  @app.post("/find-auspicious-dates")
2194
  @app.post("/api/find-auspicious-dates") # Alternative endpoint
2195
+ def find_auspicious_dates_api(req: FindAuspiciousDatesRequest, api_key: str = Depends(verify_api_key)):
2196
  """
2197
  🔍 Find Auspicious Dates (寻找吉日)
2198
 
 
2297
  # ==================== Chinese Calendar API ====================
2298
 
2299
  @app.get("/api/calendar/today")
2300
+ def get_today_calendar():
2301
  """
2302
  Get today's Chinese lunar calendar information
2303
 
 
2359
 
2360
 
2361
  @app.get("/api/calendar/range")
2362
+ def get_calendar_range(start: str, end: str):
2363
  """
2364
  Get Chinese lunar calendar information for a date range
2365
 
 
2421
 
2422
 
2423
  @app.get("/api/calendar/{date_str}")
2424
+ def get_calendar_by_date(date_str: str):
2425
  """
2426
  Get Chinese lunar calendar information for a specific date
2427
 
 
2471
 
2472
 
2473
  @app.post("/api/calendar/convert-lunar-to-solar")
2474
+ def convert_lunar_to_solar(request: LunarToSolarRequest):
2475
  """
2476
  Convert Chinese Lunar calendar date to Gregorian (Solar) calendar date
2477
 
 
2557
 
2558
 
2559
  @app.post("/api/nine-stars/analyze")
2560
+ def analyze_nine_stars(
2561
  req: NineStarsRequest,
2562
  api_key: str = Depends(verify_api_key)
2563
  ):
 
2662
 
2663
 
2664
  @app.get("/api/nine-stars/today")
2665
+ def get_today_nine_stars(
2666
  hour: int = 12,
2667
  api_key: str = Depends(verify_api_key)
2668
  ):
 
2706
 
2707
 
2708
  @app.post("/api/28-constellations/analyze")
2709
+ def analyze_28_constellations(
2710
  req: Constellation28Request,
2711
  api_key: str = Depends(verify_api_key)
2712
  ):
 
2809
 
2810
 
2811
  @app.get("/api/28-constellations/today")
2812
+ def get_today_constellation(api_key: str = Depends(verify_api_key)):
2813
  """
2814
  ⭐ Get today's 28 Lunar Mansions constellation
2815
 
 
2842
 
2843
 
2844
  @app.post("/api/28-constellations/find-auspicious")
2845
+ def find_auspicious_dates(
2846
  activity: str,
2847
  start_date: str,
2848
  end_date: str,
 
2934
 
2935
 
2936
  @app.get("/api/zodiac-fortune/today/{zodiac}")
2937
+ def get_today_zodiac_fortune(zodiac: str):
2938
  """
2939
  🐉 Get today's fortune for a specific zodiac (今日生肖运程)
2940
 
 
2984
 
2985
 
2986
  @app.get("/api/zodiac-fortune/{zodiac}/{date_str}")
2987
+ def get_zodiac_fortune_by_date(zodiac: str, date_str: str):
2988
  """
2989
  🐉 Get fortune for a specific zodiac on a specific date (指定日期生肖运程)
2990
 
 
3027
 
3028
 
3029
  @app.get("/api/zodiac-fortune/all/{date_str}")
3030
+ def get_all_zodiac_fortune(date_str: str):
3031
  """
3032
  🐉 Get fortune for ALL 12 zodiacs on a specific date (12生肖运程)
3033
 
 
3130
 
3131
  @app.post("/api/marriage-compatibility")
3132
  @app.post("/marriage-compatibility")
3133
+ def analyze_marriage_compatibility(
3134
  req: MarriageCompatibilityRequest,
3135
  api_key: str = Depends(verify_api_key)
3136
  ):
 
3256
 
3257
  @app.post("/api/fortune-score")
3258
  @app.post("/fortune-score")
3259
+ def calculate_comprehensive_fortune_score(
3260
  req: FortuneScoreRequest,
3261
  api_key: str = Depends(verify_api_key)
3262
  ):
 
3357
 
3358
  @app.get("/rituals")
3359
  @app.get("/api/rituals") # 备用路由
3360
+ def get_all_rituals(api_key: str = Depends(verify_api_key)):
3361
  """
3362
  获取所有能量仪式
3363
 
 
3399
 
3400
  @app.get("/rituals/{ritual_id}")
3401
  @app.get("/api/rituals/{ritual_id}") # 备用路由
3402
+ def get_ritual_by_id(ritual_id: str, api_key: str = Depends(verify_api_key)):
3403
  """
3404
  获取单个仪式详情
3405
 
 
3448
 
3449
  @app.post("/rituals/search")
3450
  @app.post("/api/rituals/search") # 备用路由
3451
+ def search_rituals(request: RitualSearchRequest, api_key: str = Depends(verify_api_key)):
3452
  """
3453
  搜索仪式
3454
 
 
3518
 
3519
  @app.get("/rituals/category/{category}")
3520
  @app.get("/api/rituals/category/{category}") # 备用路由
3521
+ def get_rituals_by_category(category: str, api_key: str = Depends(verify_api_key)):
3522
  """
3523
  按类别获取仪式
3524
 
 
3562
 
3563
  @app.get("/rituals/moon-phase/current")
3564
  @app.get("/api/rituals/moon-phase/current") # 备用路由
3565
+ def get_current_moon_phase_rituals(api_key: str = Depends(verify_api_key)):
3566
  """
3567
  获取当前月相适合的仪式
3568
 
 
3600
 
3601
  @app.post("/rituals/recommend")
3602
  @app.post("/api/rituals/recommend") # 备用路由
3603
+ def recommend_rituals(request: RitualRecommendRequest, api_key: str = Depends(verify_api_key)):
3604
  """
3605
  个性化仪式推荐
3606
 
 
3665
 
3666
  @app.get("/rituals/related/{ritual_id}")
3667
  @app.get("/api/rituals/related/{ritual_id}") # 备用路由
3668
+ def get_related_rituals(ritual_id: str, limit: int = 5, api_key: str = Depends(verify_api_key)):
3669
  """
3670
  获取相关仪式
3671
 
 
3710
 
3711
  @app.get("/rituals/statistics")
3712
  @app.get("/api/rituals/statistics") # 备用路由
3713
+ def get_rituals_statistics(api_key: str = Depends(verify_api_key)):
3714
  """
3715
  获取仪式统计信息
3716
 
 
3763
 
3764
  @app.post("/analyze-body-reading")
3765
  @app.post("/api/analyze-body-reading")
3766
+ def analyze_body_reading_endpoint(
3767
  req: BodyReadingRequest,
3768
  api_key: str = Depends(verify_api_key)
3769
  ):
 
3859
 
3860
  @app.post("/analyze-marriage-destiny")
3861
  @app.post("/api/analyze-marriage-destiny")
3862
+ def analyze_marriage_destiny(
3863
  req: MarriageDestinyRequest,
3864
  api_key: str = Depends(verify_api_key)
3865
  ):
 
3974
 
3975
  @app.post("/api/qimen/chart")
3976
  @app.post("/qimen-chart")
3977
+ def calculate_qimen_chart(
3978
  req: QimenChartRequest,
3979
  api_key: str = Depends(verify_api_key)
3980
  ):
 
4035
 
4036
  @app.get("/api/qimen/now")
4037
  @app.get("/qimen-now")
4038
+ def get_qimen_now(
4039
  purpose: str = "综合",
4040
  api_key: str = Depends(verify_api_key)
4041
  ):
 
4102
 
4103
  @app.post("/api/liuyao/divine")
4104
  @app.post("/liuyao-divine")
4105
+ def divine_liuyao(
4106
  req: LiuYaoRequest,
4107
  api_key: str = Depends(verify_api_key)
4108
  ):
 
4123
 
4124
  @app.get("/api/liuyao/now")
4125
  @app.get("/liuyao-now")
4126
+ def get_liuyao_now(
4127
  purpose: str = "综合",
4128
  question: str = "",
4129
  api_key: str = Depends(verify_api_key)
 
4157
 
4158
  @app.post("/api/fengshui/home-analysis")
4159
  @app.post("/fengshui-home-analysis")
4160
+ def fengshui_home_analysis(
4161
  req: FengshuiHomeRequest,
4162
  api_key: str = Depends(verify_api_key)
4163
  ):
 
4179
 
4180
  @app.post("/api/fengshui/ming-gua")
4181
  @app.post("/fengshui-ming-gua")
4182
+ def fengshui_ming_gua(
4183
  req: FengshuiMingGuaRequest,
4184
  api_key: str = Depends(verify_api_key)
4185
  ):
 
4194
 
4195
 
4196
  @app.get("/api/fengshui/zhai-gua/{facing}")
4197
+ def fengshui_zhai_gua(
4198
  facing: str,
4199
  api_key: str = Depends(verify_api_key)
4200
  ):