"""多渠道网关公开 Webhook 路由。""" from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException, Request, status channel_webhook = APIRouter(prefix="/channels", tags=["channels"]) # Webhook 公开入口最大允许请求体大小(字节)。 _MAX_WEBHOOK_PAYLOAD_SIZE = 10 * 1024 * 1024 def _get_gateway(request: Request): gateway = getattr(request.app.state, "channel_gateway", None) if gateway is None: raise HTTPException( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Channel gateway not initialized", ) return gateway async def _check_webhook_payload_size(request: Request): """依据 Content-Length 头限制公开 Webhook 请求体大小。""" content_length = request.headers.get("content-length") if content_length is not None: try: size = int(content_length) except ValueError: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid Content-Length header", ) from None if size > _MAX_WEBHOOK_PAYLOAD_SIZE: raise HTTPException( status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail="Webhook payload too large", ) @channel_webhook.post( "/{channel_type}/webhook", dependencies=[Depends(_check_webhook_payload_size)], ) async def channel_webhook_entry( channel_type: str, request: Request, ): """多渠道网关公开 Webhook 入口。""" gateway = _get_gateway(request) return await gateway.handle_webhook(channel_type, request)