Repository navigation
HTTP API
事实来源:主仓
pr-88@a312645,路由清单与 schema 见src/souwen/server/routes/、主仓api-reference.md与/docs。
启动 API 服务后,所有 REST 端点都派发到 souwen.facade.*——和 CLI / Python API 走同一条路。本页按"端点目的"分组介绍最常用调用,错误码、限流、认证细节都在这里。完整字段表去主仓 docs/。
souwen serve --host 0.0.0.0 --port 8000 # 本地默认 8000
docker run -p 49265:49265 ghcr.io/blueskyxn/souwen # 镜像默认 49265| 入口 | 用途 |
|---|---|
GET / |
expose_docs=true 时重定向 /docs;否则返回 JSON 元信息 |
GET /docs |
Swagger UI |
GET /redoc |
ReDoc |
GET /openapi.json |
OpenAPI 3.1 schema |
GET /panel |
Web UI(浏览器入口 /panel#/,前端 router 处理 hash) |
GET /health |
容器存活探针,无需认证 |
GET /readiness |
K8s readiness(仅本地检查),无需认证 |
生产建议设
expose_docs=false关闭/docs/redoc/openapi.json;/health/readiness/api/v1/*不受影响。
所有需鉴权的端点用 Authorization: Bearer <password>:
export AUTH="Authorization: Bearer $SOUWEN_ADMIN_PASSWORD"
curl -H "$AUTH" http://localhost:8000/api/v1/admin/config三角色映射(详见 Authentication and Roles):
| 端点群 | 角色要求 | 中间件 |
|---|---|---|
/api/v1/search/* · /api/v1/sources · /api/v1/whoami · /api/v1/wayback/cdx · /api/v1/wayback/check · /api/v1/youtube/* · /api/v1/bilibili/* · /api/v1/summarize · /api/v1/fetch/summarize
|
User(未设密码时开放) | check_search_auth |
/api/v1/fetch · /api/v1/links · /api/v1/sitemap
|
Admin(高 SSRF 风险) | require_auth |
/api/v1/admin/* · /api/v1/admin/wayback/save
|
Admin(默认锁定) | require_auth |
/health · /readiness · /docs · /panel
|
无 | — |
GET /api/v1/whoami 返回当前角色与 features,前端用它做导航/页面级渲染:
{
"role": "admin",
"features": {
"search": true, "raw_search": true, "fetch": true,
"wayback_save": true,
"config_read": "full", "config_write": true,
"sources_config_read": true, "sources_config_write": true,
"proxy_admin": true, "warp_admin": true,
"doctor": true, "doctor_full": true
},
"guest_enabled": false
}| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
q |
string (1-500) | 必填 | 关键词 |
sources |
string | "openalex,arxiv" |
源列表,逗号分隔 |
per_page |
int (1-100) | 10 |
每源返回数 |
timeout |
float (1-300) | null | null |
端点硬超时;超时返回 504 |
curl "http://localhost:8000/api/v1/search/paper?q=transformer&per_page=5"响应:
{
"query": "transformer",
"sources": ["openalex", "arxiv"],
"results": [/* ... 多个 SearchResponse */],
"total": 20,
"meta": {
"requested": ["openalex", "arxiv"],
"succeeded": ["openalex", "arxiv"],
"failed": []
}
}- 任意源失败 → 出现在
meta.failed,不影响其他源。 -
全部源失败 →
502 bad_gateway。 - 超过
timeout→504 gateway_timeout。
参数同 paper,仅默认源不同:sources 默认 "google_patents"。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
q |
string (1-500) | 必填 | 关键词 |
engines |
string | "duckduckgo,bing" |
引擎列表 |
per_page |
int (1-50) | 10 |
每引擎条数(主名) |
max_results |
int (1-50) | null | null |
旧版别名;显式提供时优先于 per_page
|
timeout |
float (1-300) | null | null |
硬超时 |
兼容性:旧客户端继续用
max_results也可;新客户端推荐per_page。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
q |
string (1-500) | 必填 | 关键词 |
max_results |
int (1-100) | 20 |
最大结果数 |
region |
string | "wt-wt" |
wt-wt 全球 / cn-zh 中国 |
safesearch |
string | "moderate" |
on / moderate / off
|
timeout |
float (1-120) | null | null |
硬超时 |
返回当前可用源列表(已过滤"必须凭据缺失/自建实例 URL 缺失");从运行时 live registry 派生,插件注册/注销实时生效。
{
"paper": [
{
"name": "openalex",
"needs_key": false,
"key_requirement": "optional",
"auth_requirement": "optional",
"credential_fields": ["openalex_email"],
"optional_credential_effect": "politeness",
"integration_type": "open_api",
"risk_level": "low",
"stability": "stable",
"default_enabled": true,
"description": "OpenAlex 开放学术数据"
}
],
"patent": [...],
"general": [...],
"professional": [...],
"fetch": [...]
}
general/professional是 web domain 的兼容拆分;knowledge显示为wiki;archive与跨域抓取归入fetch。
curl -X POST "http://localhost:8000/api/v1/fetch" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{
"urls": ["https://example.com"],
"provider": "builtin",
"timeout": 30
}'| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
urls |
list[str] (1-20) |
必填 | 目标 URL |
provider |
string | "builtin" |
21 个 provider 之一 |
timeout |
float (1-120) | 30 |
单 URL 超时秒 |
安全特性:
- SSRF 防护:DNS 解析所有 A/AAAA 记录;私网(10/8、172.16/12、192.168/16)/ 回环 / 链路本地 / 保留段 / 组播段一律拒绝。
- 逐跳重校验:重定向跟随过程中每一跳重新校验目标 IP,防止多跳 SSRF。
- 被拦截的 URL 仍出现在
results中,但error字段为ssrf_blocked类原因。
curl -H "$AUTH" "http://localhost:8000/api/v1/links?url=https://example.com&limit=100"| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
url |
string | 必填 | 页面 URL |
base_url |
string | null | 仅保留前缀匹配 |
limit |
int (1-1000) | 100 | 最多链接数 |
curl -H "$AUTH" "http://localhost:8000/api/v1/sitemap?url=https://example.com&discover=true"| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
url |
string | 必填 | sitemap URL 或网站根 URL |
discover |
bool | false | true 时从 robots.txt 自动发现 |
limit |
int (1-50000) | 1000 | 最多 URL 数 |
支持 sitemap.xml / sitemap index / gzipped。
curl "http://localhost:8000/api/v1/youtube/trending?region=US&max_results=20"
curl "http://localhost:8000/api/v1/youtube/video/dQw4w9WgXcQ"
curl "http://localhost:8000/api/v1/youtube/transcript/dQw4w9WgXcQ?lang=en" # 零配额错误码映射:BilibiliNotFound→404 · BilibiliAuthRequired→401 · BilibiliRateLimited→429 · BilibiliRiskControl→403 · BilibiliError→502。
curl "http://localhost:8000/api/v1/bilibili/video/BV1xx411c7m9"
curl "http://localhost:8000/api/v1/bilibili/search?keyword=编程&max_results=20&order=pubdate"
curl "http://localhost:8000/api/v1/bilibili/search/users?keyword=雷军&page=1"
curl "http://localhost:8000/api/v1/bilibili/search/articles?keyword=AI"# User
curl "http://localhost:8000/api/v1/wayback/cdx?url=https://example.com&from=20200101&to=20240101&limit=50"
curl "http://localhost:8000/api/v1/wayback/check?url=https://example.com×tamp=20240301"
# Admin(IA 全局 ~15 req/min,注意限流)
curl -X POST -H "$AUTH" "http://localhost:8000/api/v1/admin/wayback/save?url=https://example.com"6. LLM 摘要端点(详见 LLM Summary)
curl -X POST "http://localhost:8000/api/v1/summarize" \
-H "Content-Type: application/json" \
-d '{"q": "transformer", "domain": "paper", "limit": 5}'
curl -X POST "http://localhost:8000/api/v1/fetch/summarize" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"urls": ["https://example.com"], "provider": "builtin"}'- 端点始终注册,但运行时要求
llm.enabled=true且llm.api_key配置可用,否则503 service_unavailable。
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/api/v1/admin/config |
当前配置(敏感字段 ***) |
POST |
/api/v1/admin/config/reload |
重载 YAML + env |
GET |
/api/v1/admin/config/yaml |
读 YAML 或返回模板 |
PUT |
/api/v1/admin/config/yaml |
保存并重载 |
GET |
/api/v1/admin/doctor |
数据源健康摘要(不发真实请求) |
GET |
/api/v1/admin/ping |
仅 Admin 鉴权探活 |
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/api/v1/admin/sources/config |
全部源频道配置 |
GET |
/api/v1/admin/sources/config/{name} |
单源 |
PUT |
/api/v1/admin/sources/config/{name} |
运行时更新(不持久化) |
| 方法 | 路径 | 说明 |
|---|---|---|
GET/PUT
|
/api/v1/admin/proxy |
全局 proxy + proxy_pool |
GET/PUT
|
/api/v1/admin/http-backend |
全局默认 + 按源覆盖 |
详见 Network and WARP。
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/api/v1/admin/warp |
状态 |
GET |
/api/v1/admin/warp/config |
配置视图 |
GET |
/api/v1/admin/warp/modes |
5 种模式可用性 |
POST |
/api/v1/admin/warp/enable |
启用 |
POST |
/api/v1/admin/warp/disable |
禁用 |
POST |
/api/v1/admin/warp/register |
注册(`backend=wgcf |
POST |
/api/v1/admin/warp/test |
测试出口 |
POST |
/api/v1/admin/warp/switch |
切换模式 |
GET |
/api/v1/admin/warp/events |
SSE 实时事件流 |
GET |
/api/v1/admin/warp/components |
组件状态(usque/wireproxy/wgcf) |
POST |
/api/v1/admin/warp/components/install |
运行时安装组件 |
POST |
/api/v1/admin/warp/components/uninstall |
卸载 |
详见 Plugins。
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/api/v1/admin/plugins |
全部插件列表 + restart_required + install_enabled
|
GET |
/api/v1/admin/plugins/{name} |
详情 |
GET |
/api/v1/admin/plugins/{name}/health |
调插件 health_check
|
POST |
/api/v1/admin/plugins/{name}/enable |
启用(重启生效) |
POST |
/api/v1/admin/plugins/{name}/disable |
禁用 + 运行时尽力卸载 |
POST |
/api/v1/admin/plugins/install |
pip 安装(需 SOUWEN_ENABLE_PLUGIN_INSTALL=1) |
POST |
/api/v1/admin/plugins/uninstall |
pip 卸载 |
POST |
/api/v1/admin/plugins/reload |
追加扫描 entry points |
所有 4xx/5xx 错误统一格式:
{
"error": "rate_limited",
"detail": "请求过于频繁,每 60 秒最多 60 次",
"request_id": "a1b2c3d4e5f6"
}error 字段(机器可读)映射:
| HTTP | error |
|---|---|
| 400 | bad_request |
| 401 | unauthorized |
| 403 | forbidden |
| 404 | not_found |
| 422 | validation_error |
| 429 | rate_limited |
| 500 | internal_error |
| 502 |
bad_gateway(如所有源失败) |
| 503 |
service_unavailable(如缺必需 Key 的端点) |
| 504 | gateway_timeout |
| 其他 | error |
详见 Error Codes。
/api/v1/search/* 默认 60 req / 60 s / IP(内存滑动窗口)。配置了 trusted_proxies 时,会从受信代理转发的 X-Forwarded-For 提取真实 IP。
429 响应附带:
| Header | 含义 |
|---|---|
Retry-After |
建议重试等待秒数 |
X-RateLimit-Limit |
窗口内最大请求数 |
X-RateLimit-Remaining |
剩余配额(429 时为 0) |
X-RateLimit-Reset |
配额重置 Unix 时间戳 |
LLM 摘要单独受 llm.rate_limit_summarize / llm.rate_limit_fetch 控制。
import httpx
class SouWenClient:
def __init__(self, base_url: str, password: str | None = None):
self.base = base_url.rstrip("/")
self.headers = {"Authorization": f"Bearer {password}"} if password else {}
async def search_paper(self, q: str, sources: str = "openalex,arxiv", per_page: int = 10):
async with httpx.AsyncClient(headers=self.headers, timeout=60) as c:
r = await c.get(f"{self.base}/api/v1/search/paper",
params={"q": q, "sources": sources, "per_page": per_page})
r.raise_for_status()
return r.json()
async def fetch(self, urls: list[str], provider: str = "builtin"):
async with httpx.AsyncClient(headers=self.headers, timeout=60) as c:
r = await c.post(f"{self.base}/api/v1/fetch",
json={"urls": urls, "provider": provider})
r.raise_for_status()
return r.json()- Authentication and Roles — 角色模型 + 端点权限
- Error Codes — 错误码完整索引
- API Reference — 全部 61 路由速查
- Network and WARP — 出口网络与代理
- 主仓
api-reference.md— 字段级事实源
Last calibrated:2026-05-04 · 主仓 pr-88 @ a312645`
Home · Quick Start · Architecture · FAQ · Troubleshooting · Coverage Manifest · Contributing
权威技术文档以主仓 docs/ 与 src/ 为准。本项目仅供 Python 学习与技术研究使用,禁止用于违反法律法规或第三方服务条款的用途。