From 7c9df70724f0a28571a3ac43e2d607560974c702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E4=BF=8A=E7=94=B7?= Date: Thu, 18 Dec 2025 12:20:21 +0800 Subject: [PATCH 1/3] feat(apikey system): api key authentication adds the GET method --- .../controllers/service/app_api_controller.py | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/api/app/controllers/service/app_api_controller.py b/api/app/controllers/service/app_api_controller.py index 1731405c..f8bacc34 100644 --- a/api/app/controllers/service/app_api_controller.py +++ b/api/app/controllers/service/app_api_controller.py @@ -1,6 +1,6 @@ """App 服务接口 - 基于 API Key 认证""" import uuid -from fastapi import APIRouter, Depends, Request, Body +from fastapi import APIRouter, Depends, Request, Body, Query from sqlalchemy.orm import Session from app.db import get_db @@ -44,3 +44,30 @@ async def chat_with_agent_demo( logger.info(f"Resource ID: {resource_id}") logger.info(f"Message: {message}") return success(data={"received": True}, msg="消息已接收") + +# /v1/apps/{resource_id}/chat +@router.get("/{resource_id}/chat") +@require_api_key(scopes=["app"]) +async def chat_with_agent_demo( + resource_id: uuid.UUID, + request: Request, + api_key_auth: ApiKeyAuth = None, + db: Session = Depends(get_db), + message: str = Query(..., description="聊天消息内容"), +): + """ + Agent 聊天接口demo + + scopes: 所需的权限范围列表["app", "rag", "memory"] + + Args: + resource_id: 如果是应用的apikey传的是应用id; 如果是服务的apikey传的是工作空间id + message: 请求参数 + request: 声明请求 + api_key_auth: 包含验证后的API Key 信息 + db: db_session + """ + logger.info(f"API Key Auth: {api_key_auth}") + logger.info(f"Resource ID: {resource_id}") + logger.info(f"Message: {message}") + return success(data={"received": True}, msg="消息已接收") From 6d462c8f2cd22478e3393c184d610e36fd0ca2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E4=BF=8A=E7=94=B7?= Date: Thu, 18 Dec 2025 12:26:39 +0800 Subject: [PATCH 2/3] feat(apikey system): api key authentication delete the GET method --- .../controllers/service/app_api_controller.py | 29 +------------------ 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/api/app/controllers/service/app_api_controller.py b/api/app/controllers/service/app_api_controller.py index f8bacc34..1731405c 100644 --- a/api/app/controllers/service/app_api_controller.py +++ b/api/app/controllers/service/app_api_controller.py @@ -1,6 +1,6 @@ """App 服务接口 - 基于 API Key 认证""" import uuid -from fastapi import APIRouter, Depends, Request, Body, Query +from fastapi import APIRouter, Depends, Request, Body from sqlalchemy.orm import Session from app.db import get_db @@ -44,30 +44,3 @@ async def chat_with_agent_demo( logger.info(f"Resource ID: {resource_id}") logger.info(f"Message: {message}") return success(data={"received": True}, msg="消息已接收") - -# /v1/apps/{resource_id}/chat -@router.get("/{resource_id}/chat") -@require_api_key(scopes=["app"]) -async def chat_with_agent_demo( - resource_id: uuid.UUID, - request: Request, - api_key_auth: ApiKeyAuth = None, - db: Session = Depends(get_db), - message: str = Query(..., description="聊天消息内容"), -): - """ - Agent 聊天接口demo - - scopes: 所需的权限范围列表["app", "rag", "memory"] - - Args: - resource_id: 如果是应用的apikey传的是应用id; 如果是服务的apikey传的是工作空间id - message: 请求参数 - request: 声明请求 - api_key_auth: 包含验证后的API Key 信息 - db: db_session - """ - logger.info(f"API Key Auth: {api_key_auth}") - logger.info(f"Resource ID: {resource_id}") - logger.info(f"Message: {message}") - return success(data={"received": True}, msg="消息已接收") From 43a30b5a1fe95b20f3c29a06bda2d1e89b7e1a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E4=BF=8A=E7=94=B7?= Date: Thu, 18 Dec 2025 16:56:34 +0800 Subject: [PATCH 3/3] feat(apikey system): api key authentication qps optimization --- api/app/core/api_key_auth.py | 47 +++++++++++++++-------------- api/app/services/api_key_service.py | 2 +- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/api/app/core/api_key_auth.py b/api/app/core/api_key_auth.py index a5db49a7..d90bb00d 100644 --- a/api/app/core/api_key_auth.py +++ b/api/app/core/api_key_auth.py @@ -70,29 +70,6 @@ def require_api_key( }) raise BusinessException("API Key 无效或已过期", BizCode.API_KEY_INVALID) - rate_limiter = RateLimiterService() - is_allowed, error_msg, rate_headers = await rate_limiter.check_all_limits(api_key_obj) - if not is_allowed: - logger.warning("API Key 限流触发", extra={ - "api_key_id": str(api_key_obj.id), - "endpoint": str(request.url), - "method": request.method, - "error_msg": error_msg - }) - # 根据错误消息判断限流类型 - if "QPS" in error_msg: - code = BizCode.API_KEY_QPS_LIMIT_EXCEEDED - elif "Daily" in error_msg: - code = BizCode.API_KEY_DAILY_LIMIT_EXCEEDED - else: - code = BizCode.API_KEY_QUOTA_EXCEEDED - - raise RateLimitException( - error_msg, - code, - rate_headers=rate_headers - ) - if scopes: missing_scopes = [] for scope in scopes: @@ -138,6 +115,30 @@ def require_api_key( scopes=api_key_obj.scopes, resource_id=api_key_obj.resource_id, ) + + rate_limiter = RateLimiterService() + is_allowed, error_msg, rate_headers = await rate_limiter.check_all_limits(api_key_obj) + if not is_allowed: + logger.warning("API Key 限流触发", extra={ + "api_key_id": str(api_key_obj.id), + "endpoint": str(request.url), + "method": request.method, + "error_msg": error_msg + }) + # 根据错误消息判断限流类型 + if "QPS" in error_msg: + code = BizCode.API_KEY_QPS_LIMIT_EXCEEDED + elif "Daily" in error_msg: + code = BizCode.API_KEY_DAILY_LIMIT_EXCEEDED + else: + code = BizCode.API_KEY_QUOTA_EXCEEDED + + raise RateLimitException( + error_msg, + code, + rate_headers=rate_headers + ) + start_time = time.perf_counter() response = await func(*args, **kwargs) end_time = time.perf_counter() diff --git a/api/app/services/api_key_service.py b/api/app/services/api_key_service.py index 2d7393e3..32cd578b 100644 --- a/api/app/services/api_key_service.py +++ b/api/app/services/api_key_service.py @@ -257,7 +257,7 @@ class RateLimiterService: key = f"rate_limit:qps:{api_key_id}" async with self.redis.pipeline() as pipe: pipe.incr(key) - pipe.expire(key, 1) # 1 秒过期 + pipe.expire(key, 1, nx=True) # 1 秒过期 results = await pipe.execute() current = results[0]