Follow-up on resource_urls=public. Review turned up one authorization gap plus a
set of correctness problems in the streaming path.
Authorization:
- Embed channels were documented as excluded, but nothing enforced it. The
delegating handlers hand the visitor's own gin context to the shared
handlers, so ?resource_urls=public — and a deployment-wide
RESOURCE_URL_MODE=public — reached anonymous traffic and produced
shareable, credential-free URLs that bypass the channel-scoped
/embed/:channel_id/files proxy. ensureEmbedSession now pins the request
context to handle mode, which covers every delegated endpoint including
future ones. The downgrade is silent so a client that forwards the
parameter keeps working.
- A knowledge-base-restricted API key is refused with 403. Such a key is
already denied /files because a raw storage path cannot be bound to its
allow-list, so handing it anonymous file URLs would reopen that hole from
the other side. The default handle mode stays available to it.
Streaming:
- Rewriter.ref holds its lock across resolution. Resolver implementations keep
an unsynchronised per-provider cache, so the previous unlocked window was a
real data race for any caller sharing a StreamRewriter between goroutines —
which its own doc comment invited. Serialising also collapses a concurrent
duplicate into one signature.
- Release the holdback buffer on every path that ends a stream while the
client is still connected: a user-requested stop, an error event, and
giving up on the event store. Only completion flushed before, so the tail
generated just before a stop was silently dropped.
- A released tail carries the metadata of the event it was cut from instead of
a bare event_id.
- The maxHeldBytes safety valve aligns to a UTF-8 boundary rather than cutting
a character in half, and an unclosed "下挂载;生产部署默认关闭。
基础信息
- 基础 URL:
/api/v1 - 响应格式: JSON
- 认证方式: API Key
认证机制
所有 API 请求需要在 HTTP 请求头中包含 X-API-Key 进行身份认证:
X-API-Key: your_api_key
为便于问题追踪和调试,建议每个请求的 HTTP 请求头中添加 X-Request-ID:
X-Request-ID: unique_request_id
获取 API Key
在 web 页面完成账户注册后,请前往账户信息页面获取您的 API Key。
请妥善保管您的 API Key,避免泄露。API Key 代表您的账户身份,拥有完整的 API 访问权限。
错误处理
所有 API 使用标准的 HTTP 状态码表示请求状态,并返回统一的错误响应格式:
{
"success": false,
"error": {
"code": "错误代码",
"message": "错误信息",
"details": "错误详情"
}
}
文件与图片引用(resource:// 与直链)
响应里的图片、图表、附件默认以内部引用 resource://<handle> 返回,例如问答答案中的
。这类引用不能被浏览器直接加载,客户端需要再
调用带鉴权的 GET /files?file_path=<引用> 代理去取字节流。
如果你在把 WeKnora 集成进自己的 App,可以让服务端直接返回可加载的 http(s) 直链,省掉这一次 额外请求:
| 方式 | 用法 | 生效范围 |
|---|---|---|
| 单次请求 | 在 URL 上加 ?resource_urls=public |
仅该次请求 |
| 整个部署 | 环境变量 RESOURCE_URL_MODE=public |
所有未显式传参的请求 |
resource_urls 取值为 handle(默认,保持内部引用)或 public(返回直链);传其它值返回
400。单次请求的参数优先于环境变量,因此把部署默认设成 public 后,仍可用
?resource_urls=handle 单独退回。
支持该参数的接口:
POST /api/v1/knowledge-chat/{session_id}(SSE)POST /api/v1/agent-chat/{session_id}(SSE)GET /api/v1/sessions/continue-stream/{session_id}(SSE)GET /api/v1/messages/{session_id}/loadPOST /api/v1/knowledge-search
改写覆盖答案正文、knowledge_references(含 image_info)、Agent 执行步骤与工具结果,以及消息
上的图片附件。流式回答里跨两个 chunk 被截断的引用会先缓冲再改写,客户端拿到的始终是完整链接。
注意事项
- 需要外链能力。 直链由存储后端预签名,或由
APP_EXTERNAL_URL+/r/<token>提供。二者都不 可用时(例如 local 存储且未设APP_EXTERNAL_URL),该引用保持resource://原样,客户端 仍可回退到/files代理。详见.env.example中的APP_EXTERNAL_URL说明。 - 直链是限时匿名可读的(WeKnora 签发的 grant 2 小时,MinIO 预签名 24 小时)。任何拿到链接的 人在过期前都能读取该文件,请勿写入日志或转发给不应看到该文件的一方。
- 嵌入式(embed)渠道不支持该参数。 其访客是匿名的,
/api/v1/embed/...下的接口会强制使用handle(即使传了?resource_urls=public、或部署默认是public),图片仍走渠道维度的鉴权代理。 - 限定知识库的 API Key 不能使用
public,返回403。这类 Key 本身也被拒绝访问/files代理,若能拿到匿名直链等于绕过同一道限制。改用handle即可正常调用。 - 同一文件的直链会在有效期内复用:重复请求不会反复签发凭证,也不会每次都拿到不同的 URL,客户端 和 CDN 的缓存因此可以命中。凭证被吊销或过期后链接立即失效。
API 概览
WeKnora API 按功能分为以下几类:
| 分类 | 描述 | 文档链接 |
|---|---|---|
| 认证管理 | 用户注册、登录、令牌管理;OIDC 流程 | auth.md · OIDC认证调用流程.md |
| 空间管理 | 创建和管理空间账户 | tenant.md |
| 知识库管理 | 创建、查询和管理知识库 | knowledge-base.md |
| 知识管理 | 上传、检索和管理知识内容 | knowledge.md |
| 模型管理 | 配置和管理各种AI模型 | model.md |
| 分块管理 | 管理知识的分块内容 | chunk.md |
| 标签管理 | 管理知识库的标签分类 | tag.md |
| FAQ管理 | 管理FAQ问答对 | faq.md |
| 智能体管理 | 创建和管理自定义智能体 | agent.md |
| 会话管理 | 创建和管理对话会话 | session.md |
| 知识搜索 | 在知识库中搜索内容 | knowledge-search.md |
| 聊天功能 | 基于知识库和 Agent 进行问答 | chat.md |
| 消息管理 | 获取和管理对话消息 | message.md |
| 评估功能 | 评估模型性能 | evaluation.md |
| 初始化管理 | 知识库模型配置与 Ollama 管理 | initialization.md |
| 系统管理 | 系统信息、解析引擎、存储引擎 | system.md |
| MCP 服务 | MCP 工具服务管理 | mcp-service.md |
| 组织管理 | 组织、成员、知识库/智能体共享 | organization.md |
| Skills | 预装智能体技能 | skill.md |
| 网络搜索 | 网络搜索服务商 | web-search.md |
| 向量存储 | 向量数据库连接管理 | vector-store.md |
| 存储后端 | 对象/文件存储实例(多实例)管理 | storage-backend.md |
| IM 渠道 | 企业微信 / 飞书 / Slack 等 IM 平台对接,含渠道 CRUD 与回调 | ../IM集成开发文档.md |
| 数据源导入 | 飞书 / 企微 / Notion / Confluence 等外部数据源接入与同步 | ../数据源导入开发文档.md |