完整版 Kiln 共注册 69 条路由,可按凭据分为四类:公开端点、会话或 API Token 端点、仅限会话的端点,以及播放端点。以下清单也包含 README 未展开的管理控制台接口。
凭据模型
四种凭据各管一段职责,互不越权。
| 凭据 | 格式 | 传递方式 | 用途 |
|---|---|---|---|
| 无 | 无 | 无 | 健康探针、指标、EPG、台标、登录 |
| 会话 JWT | Ed25519(EdDSA)签名的 JWT | Authorization: Bearer <jwt>;播放端点也接受 ?token= |
管理控制台与交互式操作 |
| 管理员 API 令牌 | kiln_v1_ 前缀加 48 位 base62 字符 |
Authorization: Bearer kiln_v1_... |
脚本与自动化 |
| 播放密钥 | v1 前缀加 126 位 base62 字符 |
路径式 /p/{token}/... |
面向播放器的分发链接 |
传递方式
Authorization: Bearer 请求头同时承载会话 JWT 和管理员 API 令牌。服务端先检查值是否采用 kiln_v1_ 格式,若不是,再按会话 JWT 解析,因此不需要额外的请求头或参数来区分。
播放端点额外接受两种传递方式:
- 查询参数
?token=<jwt>,优先级高于Authorization头。 - 路径式
/p/{token}/,其中{token}是播放密钥。这种格式不读取任何请求头,链接本身就是凭据。
会话 JWT
POST /v1/auth/login 使用用户名和密码换取 JWT。令牌由 Ed25519 签名,包含签发者、受众、exp、iat、nbf 和 jti,校验时允许 30 秒的时钟偏差。有效期由 auth.token_ttl_hours 决定,默认为 24 小时。令牌还包含 role 和 channels,并与账户的 auth_revision 绑定;修改登录凭据后,此前签发的所有令牌都会立即失效。
管理端点在鉴权之后还会检查 role 必须为 admin,非管理员会话访问会得到 403 forbidden。
管理员 API 令牌
明文只在创建和轮换时返回一次,服务端仅保存 SHA-256 摘要与显示前缀。Token 有四种权限:
| 权限 | 覆盖动作 |
|---|---|
read |
读取列表、详情、状态、日志 |
write |
创建与更新 |
delete |
删除与撤销 |
refresh |
探测、预热、预览、刷新、连接测试、结束会话 |
API Token 只能访问已登记的路由。登记表共 43 条,就是本页「会话或 API Token 端点」和「管理端点」两节中标注了权限的全部条目。未登记的路由一律拒绝,拒绝原因分为:
| 原因 | 状态码 | 含义 |
|---|---|---|
revoked |
401 | Token 已停用或已撤销 |
expired |
401 | Token 已过期 |
session_required |
403 | 该路由只认登录会话 |
route_not_available |
403 | 该路由未登记给 API Token |
missing_scope |
403 | Token 缺少该路由所需权限 |
无论放行还是拒绝,每次 API Token 请求都会写入审计日志,可通过 GET /v1/admin/api-token-logs 查看。
播放密钥
播放密钥在管理控制台的「播放访问控制」中创建,可限定频道范围(all 或指定频道 ID 列表),可设置有效期、随时撤销。每次通过 /p/{token}/ 取用都会写入播放访问日志。密钥前 10 个字符作为显示前缀,日志与请求日志中的路径只保留该前缀。
通用约定
错误响应
所有错误都采用统一的 JSON 格式:
{
"error": {
"code": "invalid_request",
"message": "invalid json body"
}
}code 是稳定的机器可读标识,message 面向人。内部错误不会泄露原因,message 一律为 internal server error。
code |
典型状态码 | 场景 |
|---|---|---|
invalid_request |
400 | 请求体、参数或字段校验失败 |
unauthorized |
401 | 缺少、无效或过期的凭据 |
forbidden |
403 | 凭据有效但无权访问 |
not_found |
404 / 410 | 资源不存在或会话已消失 |
conflict |
409 | 乐观并发冲突或状态冲突 |
upstream_error |
502 | 上游拉取或探测失败 |
unavailable |
503 | 媒体分片暂未就绪 |
not_ready |
502 / 503 | 播放列表或兼容引擎尚未就绪 |
too_many_requests |
429 | 触发限流 |
internal |
500 | 服务端内部错误 |
current_password_invalid |
422 | 修改凭据时当前口令不正确 |
username_taken |
409 | 目标用户名已被占用 |
请求与响应头
每个响应都带 X-Request-ID。请求携带该头时原样返回,否则由服务端生成。默认响应还会附加 X-Content-Type-Options: nosniff、Referrer-Policy: no-referrer、X-Frame-Options: DENY、Content-Security-Policy 与 Cache-Control: no-store, no-cache, must-revalidate;EPG、台标和不可变媒体分片使用各自的缓存策略。
OPTIONS 请求直接返回 204。跨域头按 security.cors_origins 配置附加,未配置时不下发任何 CORS 头。配置了 security.public_hosts 时,Host 不在白名单内的请求返回 403 forbidden;来自回环地址的 /healthz 与 /readyz 不受此限制。
乐观并发
需要并发安全的资源使用修订号加 If-Match 头。GET /v1/admin/channels/{id} 会在 ETag 中返回当前修订号,其余资源的修订号包含在响应体的 revision 字段中。修订号不匹配时返回 409 conflict。
| 端点 | If-Match |
|---|---|
PUT /v1/admin/settings、PUT /v1/admin/egress |
必填,缺失即 409 |
/v1/admin/egress/proxies/{id} 与 /v1/admin/egress/rules/{id} 的 PUT、DELETE |
必填,缺失即 409 |
PUT、DELETE /v1/admin/epg/sources/{id} |
必填,缺失返回 428(预设源的删除除外) |
/v1/admin/api-tokens/{id} 的更新、轮换、撤销、删除 |
必填,缺失即 409 |
POST、PUT、DELETE /v1/admin/channels 系列 |
可选,提供则校验 |
/v1/admin/access-tokens/{id} 的撤销与删除 |
可选,提供则校验 |
PUT /v1/admin/channels/reorder |
用请求体中的 revisions 映射代替,缺失即 409 |
限流
POST /v1/auth/login 按客户端 IP 限流,窗口为 1 分钟,配额由 auth.login_rate_per_min 决定,默认每分钟 20 次。超出返回 429 too_many_requests。
PUT /v1/me/credentials 共用同一限流器,配额按「用户名加客户端 IP」独立计算。
公开端点
无需任何凭据。
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/ |
服务信息,同时是未匹配 GET 路径的兜底 |
GET |
/healthz |
存活探针 |
GET |
/readyz |
就绪探针 |
GET |
/metrics |
Prometheus 指标 |
GET |
/admin、/admin/ |
管理控制台静态资源 |
POST |
/v1/auth/login |
登录换取会话 JWT(限流) |
GET |
/v1/epg.xml |
XMLTV 节目单 |
GET |
/v1/epg.xml.gz |
gzip 压缩的 XMLTV 节目单 |
GET |
/v1/logo/{id} |
频道台标 |
GET /
Accept 含 text/html 时 302 跳转到 /admin,否则返回 JSON:
{ "name": "kiln", "version": "1.0.0", "commit": "dev", "admin": "/admin" }该模式同时兜底所有未匹配的 GET 路径,此时返回 404 not_found。
GET /healthz
始终返回 {"status":"ok"}。
GET /readyz
存在 DASH 入流且该频道解析到 FFmpeg 兼容引擎时,会检查 ffmpeg 是否可用;不可用返回 503 not_ready。其余情况返回 {"status":"ready"}。
GET /metrics
observe.enabled 为 false 时返回 404。启用时返回 text/plain; version=0.0.4 的 Prometheus 文本。
GET /admin、GET /admin/
返回内嵌的管理控制台。/admin/assets/ 下的静态资源支持 gzip 协商与 ETag 条件请求。
POST /v1/auth/login
请求体,多余字段会被拒绝:
{ "username": "admin", "password": "..." }成功返回 200:
{
"token": "...",
"expires_at": "2026-01-01T00:00:00Z",
"username": "admin",
"role": "admin"
}用户名或口令错误返回 401 unauthorized。
GET /v1/epg.xml、GET /v1/epg.xml.gz
返回全部频道的 XMLTV 节目单,压缩变体的 Content-Type 为 application/gzip。未配置任何 EPG 源时返回结构完整但内容为空的文档。关闭 EPG 缓存时,每次请求会先触发一次按需刷新。
GET /v1/logo/{id}
按频道的 EPG 名称(缺失时用标题)依次尝试内置候选源获取台标,成功返回图片字节,并带 Cache-Control: public, max-age=3600, stale-if-error=86400 与 X-Kiln-Logo-Source。全部候选源失败返回 502 upstream_error。
会话或 API Token 端点
登录会话或具有相应权限的管理员 API 令牌均可访问,不要求管理员角色。
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET |
/v1/me |
read |
当前凭据信息 |
GET |
/v1/channels |
read |
可见频道列表 |
GET |
/v1/status |
read |
运行状态快照 |
GET /v1/me
{
"username": "admin",
"role": "admin",
"channel_ids": [],
"credential": "session",
"scopes": null
}credential 取值为 session 或 api_token。使用 API Token 时,username 是 Token 名称,scopes 是该 Token 的权限列表。
GET /v1/channels
返回 {"channels": [...]}。每个元素包含 id、title、group、logo_url、epg_id、epg_name、epg_source、ingress、on_demand、autostart、source_url、upstream、path、disabled、prefer_height、preferred_audio_languages、sort_order、revision、play_url。
非管理员会话且带频道范围限制时,结果按 channels 声明过滤。
GET /v1/status
返回 uptime_sec、bytes_in、bytes_out、requests、errors、goroutines、session_count 与 sessions 数组。每个会话含 channel_id、mode、engine、pack_mode、fallback_reason、started_at、last_touch、state、errors、last_error,以及可选的 packager 计数块。
非管理员会话且带频道范围限制时,sessions 与 session_count 按范围过滤。
仅会话端点
只接受登录会话。管理员 API 令牌访问这些路由会被拒绝,其中 /v1/me/credentials、/v1/admin/api-tokens/* 与 /v1/admin/api-token-logs 的拒绝原因为 session_required,/v1/playlist.m3u 的拒绝原因为 route_not_available。这一限制可防止令牌自行提升权限。
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/v1/playlist.m3u |
带会话令牌的播放列表 |
PUT |
/v1/me/credentials |
修改登录凭据 |
GET |
/v1/admin/api-tokens |
列出管理员 API 令牌 |
POST |
/v1/admin/api-tokens |
创建管理员 API 令牌 |
PUT |
/v1/admin/api-tokens/{id} |
更新名称、备注、权限、启用状态、有效期 |
POST |
/v1/admin/api-tokens/{id}/rotate |
轮换明文 |
POST |
/v1/admin/api-tokens/{id}/revoke |
撤销 |
DELETE |
/v1/admin/api-tokens/{id} |
删除 |
GET |
/v1/admin/api-token-logs |
Token 审计日志 |
GET /v1/playlist.m3u
返回 application/vnd.apple.mpegurl,播放地址前缀为 /v1/play/,并把请求所用的会话令牌拼进每条播放地址。配置了 EPG 源时,播放列表头部带 x-tvg-url 指向 /v1/epg.xml.gz。
PUT /v1/me/credentials
要求管理员会话。请求体,多余字段会被拒绝:
{
"current_password": "...",
"username": "newname",
"new_password": "..."
}username 与 new_password 至少提供一个,新口令长度为 8 至 72 字节,用户名不超过 64 个字符且不含控制字符。成功返回与登录相同的结构,即一枚全新的会话令牌;旧令牌立即失效。当前口令错误返回 422 current_password_invalid,用户名被占用返回 409 username_taken。
GET /v1/admin/api-tokens
{
"tokens": [
{
"id": "...",
"name": "ci",
"token_prefix": "kiln_v1_ab12cd34",
"scopes": ["read", "write"],
"enabled": true,
"created_by": "admin",
"created_at": 0,
"expires_at": 0,
"last_used_at": 0,
"revision": 1,
"updated_at": 0
}
],
"available_scopes": ["read", "write", "delete", "refresh"]
}POST /v1/admin/api-tokens
请求体 { "name": "ci", "note": "", "scopes": ["read"], "expires_in_sec": 0 }。name 必填,expires_in_sec 为 0 表示永不过期,上限 10 年,至少要授予一项权限。返回 201:
{
"token": "kiln_v1_...",
"credential": { "id": "...", "token_prefix": "kiln_v1_ab12cd34" },
"warning": "store this token now; it will not be shown again"
}PUT /v1/admin/api-tokens/{id}
请求体字段均可选:name、note、scopes、enabled、expires_at。返回 {"credential": {...}}。
POST /v1/admin/api-tokens/{id}/rotate
生成新明文并作废旧明文,返回结构与创建一致。
POST /v1/admin/api-tokens/{id}/revoke
返回 {"ok": true}。
DELETE /v1/admin/api-tokens/{id}
返回 204,无响应体。
GET /v1/admin/api-token-logs
返回最近 100 条审计记录:
{
"logs": [
{
"id": 1,
"token_id": "...",
"token_prefix": "kiln_v1_ab12cd34",
"method": "GET",
"path": "/v1/admin/channels",
"required_scope": "read",
"decision": "allow",
"status": 200,
"remote": "127.0.0.1",
"user_agent": "curl/8",
"request_id": "...",
"created_at": 0
}
]
}被拒绝的记录额外带 reason 字段。
播放端点
播放端点分为两组路径:供会话与预览令牌使用的 /v1/play/,以及供播放密钥使用的 /p/{token}/。两组路径提供相同的三种文件格式。
| 方法 | 路径 | 凭据 | 说明 |
|---|---|---|---|
GET |
/v1/play/{id}/index.m3u8 |
会话或预览令牌 | 频道主播放列表 |
GET |
/v1/play/{id}/live/{file} |
会话或预览令牌 | 本地封装产物:媒体播放列表、分片、CMAF part |
GET |
/v1/play/{id}/u/{upstream} |
会话或预览令牌 | 已签名的上游回源代理 |
GET |
/p/{token}/playlist.m3u |
路径内的播放密钥 | 该密钥范围内的播放列表 |
GET |
/p/{token}/play/{id}/index.m3u8 |
路径内的播放密钥 | 频道主播放列表 |
GET |
/p/{token}/play/{id}/live/{file} |
路径内的播放密钥 | 本地封装产物 |
GET |
/p/{token}/play/{id}/u/{upstream} |
路径内的播放密钥 | 已签名的上游回源代理 |
三种文件格式
index.m3u8是入口。HLS 入流会拉取上游播放列表并改写地址;DASH 入流返回本地封装出的主播放列表。live/{file}提供本地封装产物,文件名不允许包含路径分隔符。发布代次变化时会带g查询参数做 307 跳转,代次已失效返回 410 并带Retry-After。低延迟场景下_HLS_msn、_HLS_part、_HLS_skip指令会被解析并阻塞等待,最长 15 秒。不可变分片带Cache-Control: private, max-age=31536000, immutable。u/{upstream}是上游回源代理。目标地址经过编码并附带 HMAC 签名sig,签名不匹配返回 403;目标主机还要通过出站白名单校验。返回内容为播放列表时会继续改写,否则原样透传。
鉴权行为
/v1/play/ 系列是否要求凭据由 security.play_require_auth 决定,默认要求。凭据可以是 ?token= 查询参数或 Authorization: Bearer 头,两者都接受会话 JWT 与预览令牌。预览令牌只在 POST /v1/admin/channels/{id}/preview 签发,有效期 5 分钟,仅限单个频道,且不能用于任何非播放端点。
/p/{token}/ 系列始终校验路径内的播放密钥,与 security.play_require_auth 无关。密钥无效、停用、已撤销或已过期返回 401 unauthorized;密钥有效但频道不在范围内返回 403 forbidden。
观众数限制
频道设置了 max_viewers 时,首次访问 index.m3u8 会签发一枚带签名的观众租约,并 307 跳转到带 viewer 查询参数的同一地址。后续请求携带该参数续租,租约签名不匹配返回 403,超出上限由会话层拒绝。
管理端点
以下路由全部位于 /v1/admin 之下,要求管理员角色。登录会话与管理员 API 令牌均可访问,令牌需要具备表中标注的权限。
频道
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET |
/v1/admin/channels |
read |
列出全部频道,含已停用 |
GET |
/v1/admin/channels/{id} |
read |
频道详情,响应带 ETag |
POST |
/v1/admin/channels |
write |
新建频道 |
PUT |
/v1/admin/channels/{id} |
write |
更新频道 |
DELETE |
/v1/admin/channels/{id} |
delete |
删除频道 |
POST |
/v1/admin/channels/enable-all |
write |
批量启用 |
POST |
/v1/admin/channels/disable-all |
write |
批量停用 |
PUT |
/v1/admin/channels/reorder |
write |
调整排序 |
GET /v1/admin/channels 返回 {"channels": [...]},字段与 GET /v1/channels 相同。
GET /v1/admin/channels/{id} 返回:
{
"channel": { "id": "demo-hls", "title": "Demo HLS" },
"egress_binding": { "mode": "auto" },
"effective_user_agent": "Kiln/1.0.0",
"revision": 3,
"updated_at": 0
}敏感请求头(authorization、proxy-authorization、cookie,以及名称含 token、secret、api-key 的头)在响应中被置空。写回时留空即保留原值。egress_binding.mode 取值为 auto、direct 或 profile,后者附带 profile_id。
POST、PUT 的请求体是频道对象,可附加 egress 子对象:
{
"id": "demo-hls",
"title": "Demo HLS",
"ingress": "hls",
"source_url": "https://example.com/live/index.m3u8",
"egress": { "mode": "profile", "profile_id": "eu-1" }
}egress.new_proxy 可以在同一次请求中快速新建代理线路,但不能与既有 profile_id 同时使用。返回 {"ok": true, "id": "demo-hls", "egress_profile_id": "..."}。修订号不匹配返回 409,校验失败返回 400。
enable-all 与 disable-all 返回 {"ok": true, "changed": 12, "channel_ids": [...]}。
reorder 的请求体是 {"ids": [...], "revisions": {"demo-hls": 3}},两者都必填。
会话、探测与预览
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
POST |
/v1/admin/channels/{id}/probe |
refresh |
探测已保存频道的源 |
POST |
/v1/admin/source-probes |
refresh |
探测尚未保存的频道草稿 |
POST |
/v1/admin/channels/{id}/warmup |
refresh |
预热频道会话 |
POST |
/v1/admin/channels/{id}/preview |
refresh |
签发预览播放地址 |
DELETE |
/v1/admin/sessions/{id} |
refresh |
结束频道会话 |
非 DASH 频道的探测返回 {"ok": true, "status": 200, "content_type": "...", "final_url": "...", "dur_ms": 42},source-probes 额外返回 proxy_id。返回的 URL 会去掉用户名、口令与查询串。
DASH 频道的探测返回 {"ok": true, "dur_ms": 1200, "inspection": {...}},inspection 是清单检查结果,包含原生引擎是否支持、建议引擎与兼容性原因。未配置全局媒体密钥时返回 400。
source-probes 的请求体与频道写入相同,可带 egress 指定本次探测走的线路,用于保存前验证连通性。
warmup 返回 202 {"state": "starting"}。
preview 返回 201:
{
"play_url": "https://kiln.example.com/v1/play/demo-hls/index.m3u8?token=...",
"expires_at": "2026-01-01T00:05:00Z"
}DELETE /v1/admin/sessions/{id} 返回 204。
EPG
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET |
/v1/admin/epg/presets |
read |
内置源预设 |
GET |
/v1/admin/epg/sources |
read |
已配置的源与运行状态 |
POST |
/v1/admin/epg/sources |
write |
新增源 |
PUT |
/v1/admin/epg/sources/{id} |
write |
更新源 |
DELETE |
/v1/admin/epg/sources/{id} |
delete |
删除源,预设源改为隐藏 |
GET |
/v1/admin/epg/matches |
read |
频道与节目单的匹配结果 |
POST |
/v1/admin/epg/refresh |
refresh |
立即刷新全部启用的源 |
GET /v1/admin/epg/sources 返回 {"sources": [...], "statuses": [...]}。sources 中每项为 {"source": {...}, "enabled": true, "revision": 1, "updated_at": 0};statuses 每项含 source_id、last_attempt、last_success、stale、error、channel_count、programme_count、available 与 metadata。
源的写入体为 {"id": "...", "name": "...", "url": "...", "timezone": "...", "proxy": "direct", "enabled": true},多余字段会被拒绝。id 必填;URL 必须是 http 或 https;timezone 必须是有效的 IANA 时区;proxy 为 auto 或某条已配置线路的 ID,缺省为 direct。修改预设源时可以只提交需要覆盖的字段,其余仍使用预设值。创建返回 201、更新返回 200,都带 {"ok": true, "source": {...}}。
GET /v1/admin/epg/matches 返回 {"matches": [...]},每项含 channel_id、status,以及可选的 match、candidates、logo_candidates。
POST /v1/admin/epg/refresh 在没有任何启用源时返回 409,否则返回 {"ok": true, "statuses": [...]}。部分源失败时 ok 为 false,逐源结果见 statuses。
上游
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET |
/v1/admin/upstreams |
read |
列出配置文件中定义的上游 |
返回 {"upstreams": [{"id": "main", "base_url": "https://example.com/live"}]}。
播放密钥
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET |
/v1/admin/access-tokens |
read |
列出播放密钥 |
POST |
/v1/admin/access-tokens |
write |
创建播放密钥 |
POST |
/v1/admin/access-tokens/{id}/revoke |
delete |
撤销 |
DELETE |
/v1/admin/access-tokens/{id} |
delete |
删除 |
列表返回 {"access_tokens": [...]},每项含 id、name、token_prefix、scope、enabled、note、created_at、last_used_at、revoked_at、expires_at、revision,不含明文。
创建的请求体为 {"name": "...", "note": "...", "channel_ids": ["demo-hls"], "expires_in_sec": 0}。channel_ids 为空表示全部频道,expires_in_sec 为 0 表示永不过期,上限 10 年。返回 201:
{
"id": "...",
"name": "living-room",
"token": "v1...",
"token_prefix": "v1AbCdEfGh",
"scope": "...",
"playlist_url": "https://kiln.example.com/p/v1.../playlist.m3u",
"created_at": 0,
"expires_at": 0,
"warning": "store this token now; it will not be shown again"
}撤销与删除均返回 {"ok": true}。
播放访问日志
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET |
/v1/admin/access-logs |
read |
查询播放访问日志 |
DELETE |
/v1/admin/access-logs |
delete |
清空播放访问日志 |
查询支持 limit 与 token_id 两个参数,返回 {"access_logs": [...]},每条含 id、token_id、token_prefix、path、channel_id、status、remote、created_at。路径中的密钥已被截断为显示前缀。清空返回 {"deleted": 128}。
日志按 access_log_retention_days 设置自动清理,缺省保留 30 天。
设置
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET |
/v1/admin/settings |
read |
读取运行时设置 |
PUT |
/v1/admin/settings |
write |
写入运行时设置 |
读取返回配置文件中的 listen、cors_origins、public_hosts、play_require_auth,加上可在运行时修改的 public_base_url、access_log_retention_days 与当前 revision。
写入的请求体为 {"public_base_url": "https://kiln.example.com", "access_log_retention_days": "30"},两个字段都是字符串,保留天数取值范围为 1 至 3650。必须携带 If-Match,缺失返回 409。
导入与导出
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
POST |
/v1/admin/import/m3u |
write |
预览或应用 M3U 导入 |
POST |
/v1/admin/exports/m3u |
write |
导出播放列表文件 |
导入的请求体为 {"content": "#EXTM3U...", "apply": false, "revisions": {}}。apply 为 false 时只做解析预览,为 true 时写入,此时需要在 revisions 中带上预览阶段拿到的频道修订号。返回 {"preview": true, "count": 30, "created": 12, "updated": 3, "skipped": 15, "entries": [...]}。任一频道在预览之后被改动过则返回 409。
导出返回 201,Content-Type 为 application/vnd.apple.mpegurl,Content-Disposition 为 attachment; filename="kiln-playlist.m3u"。导出会自动创建一枚名为 M3U export 的播放密钥并写进播放地址,不会泄露会话令牌或管理员 Token。
出站网络
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET |
/v1/admin/egress |
read |
读取出站配置 |
PUT |
/v1/admin/egress |
write |
整体替换出站配置 |
POST |
/v1/admin/egress/proxies |
write |
新建代理线路 |
PUT |
/v1/admin/egress/proxies/{id} |
write |
更新代理线路 |
DELETE |
/v1/admin/egress/proxies/{id} |
delete |
删除代理线路 |
POST |
/v1/admin/egress/rules |
write |
新建路由规则 |
PUT |
/v1/admin/egress/rules/{id} |
write |
更新路由规则 |
DELETE |
/v1/admin/egress/rules/{id} |
delete |
删除路由规则 |
POST |
/v1/admin/egress/test |
refresh |
连通性测试 |
读取返回:
{
"default": "direct",
"playlist_policy": "rewrite",
"docker_proxy_host": "host.docker.internal",
"proxies": [
{
"id": "eu-1",
"name": "eu-1",
"url": "http://proxy.example.com",
"disabled": false,
"credential_configured": true,
"revision": 2
}
],
"rules": [],
"source": "sqlite",
"revision": 5
}代理地址在响应中只保留协议与主机,凭据是否配置由 credential_configured 表示。写入时若地址的协议与主机未变且未带凭据,已保存的凭据会被保留。
代理线路必须提供 id 和 url。地址协议仅支持 http、https、socks5 和 socks5h,且 id 不能使用保留值 direct。路由规则的 kind 可设为 host_suffix、host_exact、channel_id、host_regex 或 url_regex;保存正则规则前,Kiln 会先检查表达式是否有效。规则不能引用不存在或已停用的线路。playlist_policy 可设为 rewrite、passthrough 或 auto。删除线路时,引用它的规则也会一并删除;如果它是默认线路,默认出口会恢复为 direct。
单条增删改在服务端读取当前配置、套用改动、整体校验后写回,因此同样受 If-Match 保护。
连通性测试的请求体:
{
"target": "custom",
"url": "https://example.com/live/index.m3u8",
"channel_id": "demo-hls",
"proxy_id": "eu-1"
}target 取 bing 时使用内置公网探测地址,取 source 或 custom 时必须提供 url 且目标必须是公网地址,缺省在没有 url 时按内置地址处理。proxy_url 可以直接测试一条尚未保存的线路,draft 可以整体测试一份尚未保存的配置草稿。响应始终是 200,结果在字段里:
{
"ok": true,
"reachable": true,
"outcome": "success",
"status": 200,
"proxy_id": "eu-1",
"via_proxy": "eu-1",
"reason": "rule:eu",
"rewrite": true,
"final_url": "https://example.com/live/index.m3u8",
"dur_ms": 180,
"target": "custom"
}失败时 ok 为 false,outcome 取值为 blocked、dns、timeout、tls、proxy、proxy_auth、http_error 或 network,并附 error 描述。
Lite 变体
Lite 二进制只注册 7 条路由,没有管理控制台、管理 API、EPG、指标与路径式播放密钥。频道来自配置文件的静态目录,不使用 SQLite。
| 方法 | 路径 | 凭据 |
|---|---|---|
GET |
/healthz |
无 |
GET |
/readyz |
无 |
POST |
/v1/auth/login |
无(限流) |
GET |
/v1/playlist.m3u |
会话令牌 |
GET |
/v1/play/{id}/index.m3u8 |
会话令牌 |
GET |
/v1/play/{id}/live/{file} |
会话令牌 |
GET |
/v1/play/{id}/u/{upstream} |
会话令牌 |
差异要点:
/readyz恒定返回就绪,不做兼容引擎检查。/v1/playlist.m3u走播放鉴权而非会话鉴权,因此受security.play_require_auth控制,凭据可用Authorization: Bearer头或?token=查询参数。- 错误响应格式与完整版一致。
- 响应头只设置
X-Content-Type-Options、Referrer-Policy、Cache-Control与 CORS,没有X-Request-ID、CSP 与X-Frame-Options。 - 主机白名单校验与
OPTIONS处理与完整版相同。