更新动态翻译的后端保护
This commit is contained in:
parent
e068850e4c
commit
4be4208278
|
|
@ -1,12 +1,10 @@
|
||||||
from typing import Tuple
|
from typing import Tuple, Dict
|
||||||
from wsgiref import headers
|
|
||||||
|
|
||||||
|
import aioredis
|
||||||
import httpx
|
import httpx
|
||||||
import random
|
import random
|
||||||
import json
|
import json
|
||||||
from hashlib import md5
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
|
|
||||||
from app.models import User
|
from app.models import User
|
||||||
|
|
@ -92,6 +90,31 @@ async def baidu_translation(query: str, from_lang: str, to_lang: str):
|
||||||
return "\n".join([item["dst"] for item in data["trans_result"]])
|
return "\n".join([item["dst"] for item in data["trans_result"]])
|
||||||
|
|
||||||
|
|
||||||
|
redis = aioredis.from_url("redis://localhost", encoding="utf-8", decode_responses=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def rate_limiter(
|
||||||
|
user: Tuple[User, Dict] = Depends(get_current_user),
|
||||||
|
limit: int = 2,
|
||||||
|
window: int = 1
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
限制每个 IP 在 window 秒内最多 limit 次请求
|
||||||
|
"""
|
||||||
|
client_ip = user[0].id
|
||||||
|
key = f"rate limit {client_ip}"
|
||||||
|
|
||||||
|
count = await redis.get(key)
|
||||||
|
|
||||||
|
if count is None:
|
||||||
|
# 第一次请求 → 设置计数和过期时间
|
||||||
|
await redis.set(key, 1, ex=window)
|
||||||
|
elif int(count) < limit:
|
||||||
|
await redis.incr(key)
|
||||||
|
else:
|
||||||
|
raise HTTPException(status_code=429, detail=f"Too many requests")
|
||||||
|
|
||||||
|
|
||||||
@translator_router.post('/translate', response_model=TransResponse)
|
@translator_router.post('/translate', response_model=TransResponse)
|
||||||
async def translate(
|
async def translate(
|
||||||
translate_request: TransRequest,
|
translate_request: TransRequest,
|
||||||
|
|
@ -105,12 +128,21 @@ async def translate(
|
||||||
return TransResponse(translated_text=text)
|
return TransResponse(translated_text=text)
|
||||||
|
|
||||||
|
|
||||||
@translator_router.post('/translate/debug')
|
@translator_router.post('/translate/debug', dependencies=[Depends(rate_limiter)])
|
||||||
async def test_translate(
|
async def test_translate(
|
||||||
query: str,
|
query: str,
|
||||||
from_lang: str = "auto",
|
from_lang: str = "auto",
|
||||||
to_lang: str = 'zh',
|
to_lang: str = 'zh',
|
||||||
admin_user: Tuple[User, dict] = Depends(is_admin_user)
|
admin_user: Tuple[User, dict] = Depends(is_admin_user)
|
||||||
):
|
):
|
||||||
|
"""
|
||||||
|
尝试使用多次翻译请求接口,要求在前端监听输入在约300ms左右内保持不输入再传入,
|
||||||
|
同时后端检查避免多次恶意访问
|
||||||
|
:param query: 待翻译文本
|
||||||
|
:param from_lang: 源语言,默认auto,百度API自动检测
|
||||||
|
:param to_lang: 目标语言,不允许auto
|
||||||
|
:param admin_user: 测试接口,仅管理员权限可用
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
raw = await baidu_translation(query, from_lang, to_lang)
|
raw = await baidu_translation(query, from_lang, to_lang)
|
||||||
return TransResponse(translated_text=raw)
|
return TransResponse(translated_text=raw)
|
||||||
|
|
|
||||||
2
main.py
2
main.py
|
|
@ -46,7 +46,7 @@ app.add_middleware(
|
||||||
|
|
||||||
register_tortoise(
|
register_tortoise(
|
||||||
app=app,
|
app=app,
|
||||||
config=TORTOISE_ORM,
|
config=ONLINE_SETTINGS,
|
||||||
)
|
)
|
||||||
|
|
||||||
app.include_router(users_router, tags=["User API"], prefix="/users")
|
app.include_router(users_router, tags=["User API"], prefix="/users")
|
||||||
|
|
|
||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
|
|
@ -47,6 +47,7 @@ class Settings(BaseSettings):
|
||||||
SECRET_KEY: str
|
SECRET_KEY: str
|
||||||
BAIDU_APPID: str
|
BAIDU_APPID: str
|
||||||
BAIDU_APPKEY: str
|
BAIDU_APPKEY: str
|
||||||
|
REDIS_URL: str
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
env_file = '.env'
|
env_file = '.env'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue