生产把应用挂在域名根、路由带 /api/v1 前缀,request.base_url 里没有前缀, 拼出来的地址少了这一段;本地被 Vite 的代理掩盖了。改成从 base_url 截站点根、 前缀一律取 settings.api_prefix,并补一条断言把这个差异钉住。
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
@@ -45,6 +45,7 @@ from fastapi.responses import PlainTextResponse
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from ..config import get_settings
|
||||
from ..db import bind_tenant
|
||||
from ..deps import AdminDep, SessionDep
|
||||
from ..errors import AppError, ErrorCode
|
||||
@@ -417,8 +418,14 @@ def _channel_out(channel: BotChannel) -> dict[str, Any]:
|
||||
|
||||
|
||||
def _webhook_url(request: Request, token: str) -> str:
|
||||
base = str(request.base_url).rstrip("/")
|
||||
return f"{base}/integrations/clawbot/{token}"
|
||||
"""拼出机器人要打的那个地址。
|
||||
|
||||
不能直接用 `request.base_url`:生产上应用挂在域名根、路由带 `/api/v1` 前缀,
|
||||
base_url 里没有前缀,拼出来的地址会 405(本地被 Vite 代理掩盖过这个差异)。
|
||||
所以站点根从 base_url 里截,前缀一律取 `settings.api_prefix`。
|
||||
"""
|
||||
base = str(request.base_url).split("/api/")[0].rstrip("/")
|
||||
return f"{base}{get_settings().api_prefix}/integrations/clawbot/{token}"
|
||||
|
||||
|
||||
@admin_router.get("/{ws_id}/integrations")
|
||||
|
||||
@@ -197,3 +197,11 @@ async def test_member_cannot_manage_channels(client: AsyncClient) -> None:
|
||||
)
|
||||
assert resp.status_code == 403
|
||||
assert resp.json()["code"] in (3004, 3003)
|
||||
|
||||
|
||||
async def test_webhook_url_carries_api_prefix(client: AsyncClient) -> None:
|
||||
"""回调地址必须带 /api/v1:生产上应用挂在域名根,漏了前缀就是 405。"""
|
||||
user = await login(client)
|
||||
ws = await create_workspace(client, user, "微信地址")
|
||||
channel = await _channel(client, user, ws)
|
||||
assert channel["webhook_url"].endswith(f"/api/v1/integrations/clawbot/{channel['token']}")
|
||||
|
||||
Reference in New Issue
Block a user