Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,14 @@ pnpm run dev

修改 backend/.env.dev 的环境变量 **REDIS_URL**

如需调整前端跨域来源,可在 `backend/.env.dev` 中配置:

```bash
CORS_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
```

不建议在需要携带凭据的场景下使用 `CORS_ALLOW_ORIGINS=*`。

配置API Key

1. 使用 WebUI
Expand Down
8 changes: 8 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ It is recommended to use models with strong capabilities and large parameter cou

Copy `/frontend/.env.example` to `/frontend/.env.development` (remove the `.example` suffix)

If you need to customize allowed frontend origins, set this in `backend/.env.dev`:

```bash
CORS_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
```

Avoid `CORS_ALLOW_ORIGINS=*` when requests need credentials.

2. Install Dependencies

Clone the project
Expand Down
26 changes: 19 additions & 7 deletions backend/app/config/setting.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,39 @@

class ApiType(str, Enum):
"""LLM API 类型。"""

OPENAI_CHAT = "openai-chat"
OPENAI_RESPONSES = "openai-responses"
ANTHROPIC = "anthropic"


def parse_cors(value: str) -> list[str]:
"""将 CORS 配置字符串解析为 URL 列表。
DEFAULT_CORS_ALLOW_ORIGINS = ["http://localhost:5173", "http://127.0.0.1:5173"]


def parse_cors(value: str | list[str]) -> list[str]:
"""将 CORS 配置解析为 URL 列表。

Args:
value: 逗号分隔的 URL 字符串,或 "*" 表示允许所有来源。
value: 逗号分隔的 URL 字符串、URL 列表,或 "*" 表示允许所有来源。

Returns:
解析后的 URL 列表。
"""
if isinstance(value, list):
return [url.strip() for url in value if url.strip()]

value = value.strip()
if not value:
return []
if value == "*":
return ["*"]
if "," in value:
return [url.strip() for url in value.split(",")]
return [value]

return [url.strip() for url in value.split(",") if url.strip()]


class Settings(BaseSettings):
"""全局应用配置,从环境变量和 .env 文件加载。"""

ENV: str = "dev"

COORDINATOR_API_TYPE: Optional[ApiType] = None
Expand Down Expand Up @@ -70,7 +80,9 @@ class Settings(BaseSettings):
DEBUG: bool = True
REDIS_URL: str = "redis://redis:6379/0"
REDIS_MAX_CONNECTIONS: int = 10
CORS_ALLOW_ORIGINS: Annotated[list[str] | str, BeforeValidator(parse_cors)] = "*"
CORS_ALLOW_ORIGINS: Annotated[list[str], BeforeValidator(parse_cors)] = (
DEFAULT_CORS_ALLOW_ORIGINS
)
SERVER_HOST: str = "http://localhost:8000"
DEEPSEEK_MODEL: Optional[str] = None
DEEPSEEK_BASE_URL: Optional[str] = None
Expand Down
8 changes: 6 additions & 2 deletions backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from app.utils.log_util import logger
from fastapi.staticfiles import StaticFiles
from app.utils.cli import get_ascii_banner, center_cli_str
from app.config.setting import settings


@asynccontextmanager
Expand Down Expand Up @@ -37,10 +38,13 @@ async def lifespan(app: FastAPI):


# 跨域 CORS
cors_allow_origins = settings.CORS_ALLOW_ORIGINS
cors_allow_credentials = "*" not in cors_allow_origins

app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_origins=cors_allow_origins,
allow_credentials=cors_allow_credentials,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["*"], # 暴露所有响应头
Expand Down