fix:修复接口调用问题

This commit is contained in:
ZhangYonghao
2026-03-21 21:27:20 +08:00
parent eaefc318a6
commit 3b660203dd
5 changed files with 37 additions and 10 deletions

View File

@@ -123,7 +123,7 @@
## 内容限制和安全规则 ## 内容限制和安全规则
默认开启安全拦截,以下内容会被拒绝: `ALLOW_UNSAFE_HTML=false` 时,默认开启安全拦截,以下内容会被拒绝:
- `<script>` - `<script>`
- `<iframe>` - `<iframe>`
@@ -136,6 +136,19 @@
这是为了避免智能体把任意动态脚本直接挂到线上域名下。 这是为了避免智能体把任意动态脚本直接挂到线上域名下。
当前项目默认配置已经改为 `ALLOW_UNSAFE_HTML=true`,也就是:
- 不再拦截 `<script>``<link>` 等标签
- 返回 HTML 时不再附加严格的 CSP 头
- 适合需要 JavaScript 动态展示的页面
这意味着安全风险将由你们自己兜底,建议至少做到:
- 独立子域名部署
- 不挂载登录态 Cookie
- 不与主站后台同域
- 对智能体输出做额外审核
### 推荐约束 ### 推荐约束
- 推荐把生成 HTML 的访问域名单独隔离,例如 `html.example.com` - 推荐把生成 HTML 的访问域名单独隔离,例如 `html.example.com`
@@ -201,7 +214,7 @@ NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
| `MAX_RETENTION_DAYS` | integer | `30` | 最大允许保留天数 | | `MAX_RETENTION_DAYS` | integer | `30` | 最大允许保留天数 |
| `MAX_HTML_LENGTH` | integer | `200000` | 单次 HTML 最大字节数 | | `MAX_HTML_LENGTH` | integer | `200000` | 单次 HTML 最大字节数 |
| `API_KEY` | string | 空 | 非空时启用 `X-API-Key` 鉴权 | | `API_KEY` | string | 空 | 非空时启用 `X-API-Key` 鉴权 |
| `ALLOW_UNSAFE_HTML` | boolean | `false` | 是否关闭 HTML 安全拦截,不建议生产开启 | | `ALLOW_UNSAFE_HTML` | boolean | `true` | 是否关闭 HTML 安全拦截;当前默认开启,便于执行 JS |
## 给腾讯云智能体的最小参数说明 ## 给腾讯云智能体的最小参数说明

View File

@@ -7,4 +7,4 @@ DEFAULT_RETENTION_DAYS=7
MAX_RETENTION_DAYS=30 MAX_RETENTION_DAYS=30
MAX_HTML_LENGTH=200000 MAX_HTML_LENGTH=200000
API_KEY="" API_KEY=""
ALLOW_UNSAFE_HTML=false ALLOW_UNSAFE_HTML=true

View File

@@ -7,4 +7,4 @@ DEFAULT_RETENTION_DAYS=7
MAX_RETENTION_DAYS=30 MAX_RETENTION_DAYS=30
MAX_HTML_LENGTH=200000 MAX_HTML_LENGTH=200000
API_KEY="" API_KEY=""
ALLOW_UNSAFE_HTML=false ALLOW_UNSAFE_HTML=true

View File

@@ -49,6 +49,18 @@ CONTENT_SECURITY_POLICY = "; ".join(
) )
def build_response_headers() -> dict[str, str]:
headers = {
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "no-referrer",
"Cache-Control": "public, max-age=300",
}
if not settings.allow_unsafe_html:
headers["Content-Security-Policy"] = CONTENT_SECURITY_POLICY
return headers
def require_api_key(x_api_key: str | None = Header(default=None, alias="X-API-Key")) -> None: def require_api_key(x_api_key: str | None = Header(default=None, alias="X-API-Key")) -> None:
if not settings.api_key: if not settings.api_key:
return return
@@ -316,10 +328,5 @@ def get_html_content(unique_id: str, db: Session = Depends(get_db)) -> FileRespo
return FileResponse( return FileResponse(
path=file_path, path=file_path,
media_type="text/html", media_type="text/html",
headers={ headers=build_response_headers(),
"Content-Security-Policy": CONTENT_SECURITY_POLICY,
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "no-referrer",
"Cache-Control": "public, max-age=300",
},
) )

View File

@@ -33,6 +33,13 @@ class HTMLGenerateRequest(BaseModel):
@root_validator(pre=True) @root_validator(pre=True)
def normalize_aliases(cls, values: dict) -> dict: def normalize_aliases(cls, values: dict) -> dict:
if isinstance(values.get("body"), dict):
merged_values = dict(values["body"])
for key, value in values.items():
if key != "body" and key not in merged_values:
merged_values[key] = value
values = merged_values
alias_map = { alias_map = {
"html": "html_content", "html": "html_content",
"content": "html_content", "content": "html_content",