Admin API 文档
Shortlinker 提供完整的 HTTP Admin API 用于管理短链接,支持 CRUD、批量操作、CSV 导入/导出,以及运行时配置管理。
配置方式
Admin API 相关配置可来自 config.toml、环境变量或运行时配置(数据库)。详细配置见 配置指南。
ADMIN_TOKEN:管理员登录密码(建议生产环境显式设置;未设置时程序会在首次启动时自动生成,并写入admin_token.txt(仅一次,保存后请删除该文件))ADMIN_ROUTE_PREFIX:路由前缀(可选,默认/admin)
实际接口路径固定包含
/v1,例如默认登录地址为http://localhost:8080/admin/v1/auth/login。
鉴权方式(重要)
当前实现 不使用 Authorization: Bearer ... 头。
Admin API 使用 JWT Cookie 进行鉴权:
- Access Token Cookie:默认名
shortlinker_access,Path=/(用于访问大部分 Admin/Health 接口) - Refresh Token Cookie:默认名
shortlinker_refresh,Path={ADMIN_ROUTE_PREFIX}/v1/auth(仅用于刷新 Token)
Cookie 名称、有效期、SameSite、Secure、Domain 等可通过配置项 api.* 调整,见 配置指南。
1) 登录获取 Cookie
POST /{ADMIN_ROUTE_PREFIX}/v1/auth/login
请求体:
{ "password": "your_admin_token" }示例(把 cookie 保存到 cookies.txt):
curl -sS -X POST \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"password":"your_admin_token"}' \
http://localhost:8080/admin/v1/auth/login该接口会通过
Set-Cookie返回 access/refresh cookie;响应体不返回 token 字符串,只返回提示信息与过期时间。
2) 携带 Cookie 调用其它接口
示例:
curl -sS -b cookies.txt \
http://localhost:8080/admin/v1/links3) 刷新 Token
POST /{ADMIN_ROUTE_PREFIX}/v1/auth/refresh
示例(读取并更新 cookie):
curl -sS -X POST \
-b cookies.txt -c cookies.txt \
http://localhost:8080/admin/v1/auth/refresh4) 登出(清理 Cookie)
POST /{ADMIN_ROUTE_PREFIX}/v1/auth/logout
示例:
curl -sS -X POST -b cookies.txt -c cookies.txt \
http://localhost:8080/admin/v1/auth/logoutBase URL
默认:http://your-domain:port/admin/v1
若你修改了
ADMIN_ROUTE_PREFIX,只需把/admin替换为自定义前缀。
通用响应格式
大部分接口返回 JSON:
{
"code": 0,
"data": { /* 响应数据 */ }
}code = 0:成功code = 1:业务错误(具体原因在data.error)- HTTP 状态码用于表达错误类型(如
401/404/409/500)
链接管理
GET /links - 获取短链接列表(分页 + 过滤)
curl -sS -b cookies.txt \
"http://localhost:8080/admin/v1/links?page=1&page_size=20"查询参数:
| 参数 | 类型 | 说明 | 示例 |
|---|---|---|---|
page | Integer | 页码(从 1 开始) | ?page=1 |
page_size | Integer | 每页数量(1-100) | ?page_size=20 |
search | String | 模糊搜索短码和目标 URL | ?search=github |
created_after | RFC3339 | 创建时间过滤(晚于) | ?created_after=2024-01-01T00:00:00Z |
created_before | RFC3339 | 创建时间过滤(早于) | ?created_before=2024-12-31T23:59:59Z |
only_expired | Boolean | 仅显示已过期 | ?only_expired=true |
only_active | Boolean | 仅显示未过期 | ?only_active=true |
响应格式(分页):
{
"code": 0,
"data": [
{
"code": "github",
"target": "https://github.com",
"created_at": "2024-12-15T14:30:22Z",
"expires_at": null,
"password": null,
"click_count": 42
}
],
"pagination": {
"page": 1,
"page_size": 20,
"total": 42,
"total_pages": 3
}
}POST /links - 创建短链接
curl -sS -X POST \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"code":"github","target":"https://github.com"}' \
http://localhost:8080/admin/v1/links请求体:
{
"code": "github",
"target": "https://github.com",
"expires_at": "2024-12-31T23:59:59Z",
"password": "secret123",
"force": false
}说明:
code:短码(可选),不提供则自动生成随机短码target:目标 URL(必需)expires_at:过期时间(可选),支持相对时间(如"1d","7d","1w")或 RFC3339force:当code已存在时,是否覆盖(可选,默认false;未开启时会返回409 Conflict)password:密码保护字段(实验性)- 通过 Admin API 写入时会自动使用 Argon2 哈希(若传入的字符串已是
$argon2...格式则会原样保存) - 当前版本重定向时不验证密码,仅存储
- 通过 Admin API 写入时会自动使用 Argon2 哈希(若传入的字符串已是
GET /links/{code} - 获取指定短链接
curl -sS -b cookies.txt \
http://localhost:8080/admin/v1/links/githubPUT /links/{code} - 更新短链接
curl -sS -X PUT \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"target":"https://github.com/new-repo","expires_at":"30d"}' \
http://localhost:8080/admin/v1/links/github请求体说明:
{
"target": "https://new-url.com",
"expires_at": "7d",
"password": ""
}说明:
target必填expires_at不提供则保持原值password- 不提供:保持原值
- 传空字符串
"":清除密码 - 传明文:自动 Argon2 哈希后保存
- 传
$argon2...:视为已哈希,原样保存
DELETE /links/{code} - 删除短链接
curl -sS -X DELETE -b cookies.txt \
http://localhost:8080/admin/v1/links/githubGET /stats - 获取统计信息
curl -sS -b cookies.txt \
http://localhost:8080/admin/v1/stats响应格式:
{
"code": 0,
"data": {
"total_links": 100,
"total_clicks": 5000,
"active_links": 80
}
}批量操作
POST /links/batch - 批量创建短链接
注意:请求体是对象,字段名为
links,不是纯数组。
curl -sS -X POST \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"links":[{"code":"link1","target":"https://example1.com"},{"code":"link2","target":"https://example2.com"}]}' \
http://localhost:8080/admin/v1/links/batchPUT /links/batch - 批量更新短链接
注意:请求体字段名为
updates,每一项包含code与payload。
curl -sS -X PUT \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"updates":[{"code":"link1","payload":{"target":"https://new-example1.com"}},{"code":"link2","payload":{"target":"https://new-example2.com"}}]}' \
http://localhost:8080/admin/v1/links/batchDELETE /links/batch - 批量删除短链接
注意:请求体字段名为
codes。
curl -sS -X DELETE \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"codes":["link1","link2","link3"]}' \
http://localhost:8080/admin/v1/links/batchCSV 导出/导入
GET /links/export - 导出为 CSV
导出会生成可直接用于导入的 CSV(包含 header),字段: code,target,created_at,expires_at,password,click_count
curl -sS -b cookies.txt \
-o shortlinks_export.csv \
"http://localhost:8080/admin/v1/links/export?only_active=true"POST /links/import - 从 CSV 导入
上传 multipart/form-data:
file:CSV 文件mode(可选):冲突处理模式,skip(默认)/overwrite/error
curl -sS -X POST \
-b cookies.txt -c cookies.txt \
-F "mode=overwrite" \
-F "file=@./shortlinks_export.csv" \
http://localhost:8080/admin/v1/links/import响应:
{
"code": 0,
"data": {
"total_rows": 10,
"success_count": 9,
"skipped_count": 1,
"failed_count": 0,
"failed_items": []
}
}运行时配置管理
配置管理接口位于 /{ADMIN_ROUTE_PREFIX}/v1/config 下,返回值统一为 {code,data} 结构;敏感配置会自动掩码为 [REDACTED]。
GET /config - 获取所有配置
curl -sS -b cookies.txt \
http://localhost:8080/admin/v1/configGET /config/schema - 获取配置 Schema(元信息)
返回所有配置项的元信息(类型、默认值、是否需要重启、枚举选项等),主要用于前端动态渲染配置表单/校验。
curl -sS -b cookies.txt \
http://localhost:8080/admin/v1/config/schemaGET /config/{key} - 获取单个配置
curl -sS -b cookies.txt \
http://localhost:8080/admin/v1/config/features.random_code_lengthPUT /config/{key} - 更新配置
curl -sS -X PUT \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"value":"8"}' \
http://localhost:8080/admin/v1/config/features.random_code_lengthGET /config/{key}/history - 获取变更历史
curl -sS -b cookies.txt \
"http://localhost:8080/admin/v1/config/features.random_code_length/history?limit=10"POST /config/reload - 重新加载配置
curl -sS -X POST -b cookies.txt \
http://localhost:8080/admin/v1/config/reload认证接口补充说明
POST /auth/login:无需 Cookie;验证ADMIN_TOKEN成功后下发 CookiePOST /auth/refresh:无需 Access Cookie,但需要 Refresh CookiePOST /auth/logout:无需 Cookie;用于清理 CookieGET /auth/verify:需要 Access Cookie(中间件校验通过即有效)
Python 客户端示例(requests)
import requests
class ShortlinkerAdmin:
def __init__(self, base_url: str, admin_token: str):
self.base_url = base_url.rstrip("/")
self.session = requests.Session()
# 登录:Set-Cookie 会被 requests.Session 自动保存
resp = self.session.post(
f"{self.base_url}/admin/v1/auth/login",
json={"password": admin_token},
timeout=10,
)
resp.raise_for_status()
def get_all_links(self, page=1, page_size=20):
resp = self.session.get(
f"{self.base_url}/admin/v1/links",
params={"page": page, "page_size": page_size},
timeout=10,
)
resp.raise_for_status()
return resp.json()
def create_link(self, code, target, expires_at=None, force=False):
payload = {"code": code, "target": target, "force": force}
if expires_at:
payload["expires_at"] = expires_at
resp = self.session.post(
f"{self.base_url}/admin/v1/links",
json=payload,
timeout=10,
)
resp.raise_for_status()
return resp.json()
# 使用示例
admin = ShortlinkerAdmin("http://localhost:8080", "your_admin_token")
print(admin.get_all_links())安全建议
- 强密码:使用足够复杂的
ADMIN_TOKEN(不要使用默认的自动生成值直接上生产) - HTTPS:生产环境建议启用 HTTPS,并将
api.cookie_secure=true - 网络隔离:仅在受信任网络环境中暴露 Admin API
- 定期轮换:定期更换
ADMIN_TOKEN(并重新登录获取新 Cookie)