qBittorrent 如何编写调用 WebUI 的客户端并适配 API 变化?
【免费下载链接】qBittorrentqBittorrent BitTorrent client项目地址: https://gitcode.com/GitHub_Trending/qb/qBittorrent
你遇到的任务是:写一个脚本或程序,通过 qBittorrent 的 WebAPI 完成添加种子、同步状态、控制会话等操作,并且希望在 qBittorrent 升级后能快速发现并修复 WebAPI 的破坏性变化。完成这篇文章后,你会有一条从「验证服务可达 → 建立认证 → 拉取数据 → 执行写操作 → 对照 changelog 适配变更」的连续路径。前提是你已经安装并启动了 qBittorrent 且开启了 WebUI(默认端口 8080,见 Preferences 默认值),并知道 WebUI 的登录账号密码。
WebAPI 的暴露方式与版本查询
所有接口都挂在基础路径/api/v2/下(webapplication.cpp 中API_PATH = u"/api/v2/"_s),请求形如http://<主机>:8080/api/v2/<scope>/<action>,例如api/v2/torrents/info。
两个版本接口要区分开:
app/version:返回 qBittorrent 程序版本号(appcontroller.cpp 中返回QBT_VERSION);app/webapiVersion:返回 WebAPI 自身的版本号,当前仓库中该常量定义为2.16.2(webapplication.h 中API_VERSION {2, 16, 2})。适配 API 变化时你真正需要比对的是后者。
除auth/login被声明为公开接口(webapplication.cpp 中declarePublicAPI(u"auth/login"...))外,访问其他端点时如果没有有效会话,会直接收到 403。所以客户端的第一步永远是先认证。
认证方式一:用户名密码登录并持有会话 Cookie
WebUI 自带的登录脚本就是 WebAPI 调用的参照实现:以表单编码 POSTusername、password到auth/login(login.js)。服务端校验通过后建立会话并在响应中下发一个 httpOnly 的会话 Cookie,名称前缀为QBT_SID_(webapplication.cpp)。凭据无效时返回 401。
用 curl 验证这条路径(把USER、PASS替换为你的 WebUI 账号密码,127.0.0.1:8080替换为实际地址端口):
# 登录,成功时返回 200,并把会话 Cookie 写入 cookies.txt curl -c cookies.txt \ -d "username=USER" -d "password=PASS" \ http://127.0.0.1:8080/api/v2/auth/login # 后续请求携带 Cookie;若凭据错误,第一步会收到 401 curl -b cookies.txt http://127.0.0.1:8080/api/v2/app/version客户端需要长期保存并复用这个 Cookie:会话在服务端有超时,Cookie 过期后服务端会丢弃该会话(webapplication.cpp 中cookieSessionInitialize对过期会话直接删除)。另一个可选方式:自 2.15.0 起,WebAPI 凭据可以直接通过 HTTP Basic auth 提供,curl 写作curl -u USER:PASS http://127.0.0.1:8080/api/v2/app/version,无需先调用auth/login。
注意 CSRF 保护默认开启:非 API Key 的跨站请求会被拒绝为 401(webapplication.cpp 中的isCrossSiteRequest检查)。对 curl/脚本这类不带Origin/Referer头的客户端,服务端按宽松策略放行;但如果你要从浏览器页面跨站调用,必须改用 API Key。
认证方式二:API Key(推荐用于长期运行的客户端)
自 2.14.1 起新增了app/rotateAPIKey(生成并轮换 API Key)和app/deleteAPIKey(删除现有 Key)。先登录,再调用app/rotateAPIKey:
# 需要已登录的 Cookie;响应为 JSON:{"apiKey": "<生成的 Key>"} curl -b cookies.txt -X POST http://127.0.0.1:8080/api/v2/app/rotateAPIKey之后的每个请求携带Authorization: Bearer头即可,不再依赖 Cookie 会话:
# 将 <apiKey> 替换为上一步响应 JSON 中的 apiKey 字段值 curl -H "Authorization: Bearer <apiKey>" http://127.0.0.1:8080/api/v2/sync/maindataAPI Key 行为有两处与 Cookie 会话不同(webapplication.cpp):
- 使用
Bearer认证时跳过 CSRF 检查; - 使用
Bearer认证访问auth/*端点会返回 403——API Key 会话不需要也不允许再走登录/登出。
如果服务端从未配置过 Key,app/rotateAPIKey的调用仍会生效(它生成并写入新 Key);Key 会保存到偏好项web_ui_api_key(appcontroller.cpp),也可以在 WebUI 偏好界面查看/轮换。
拉取数据:sync/maindata 与 rid 增量机制
状态同步主接口是sync/maindata,它通过rid(response id)实现增量更新(synccontroller.cpp):
# 首次调用不带 rid,返回完整快照(full_update 为 true)及一个 rid curl -b cookies.txt "http://127.0.0.1:8080/api/v2/sync/maindata" # 之后把上一次响应中的 rid 作为查询参数传回,只获取增量 curl -b cookies.txt "http://127.0.0.1:8080/api/v2/sync/maindata?rid=上次返回的rid"响应包含full_update、rid以及torrents、categories、tags、trackers、server_state等字段(键定义见 synccontroller.cpp)。WebUI 自身客户端的写法可作参照:请求带cache: "no-store",每次从响应中取出新的rid用于下一次轮询(client.js 中syncMainData)。你的客户端应实现同样的循环:记录rid→ 轮询 → 更新本地状态 → 若full_update为 true 则整体重建。
执行写操作:先约定好状态码语义
写操作集中在torrents/*、transfer/*、app/setPreferences等端点,参数以表单字段或查询参数传递。以下状态码约定是客户端必须处理的,都来自 WebAPI_Changelog.md:
| 场景 | 行为 | 版本 |
|---|---|---|
torrents/add | 响应包含success_count、pending_count、failure_count、added_torrent_ids;pending_count非零时返回 202,全部失败时返回 409 | 2.14.0+ |
| 响应体无数据 | 返回204 No Content(部分端点过渡期仍返回 200 OK) | 2.11.8+ |
| 端点不存在 | 错误消息为Endpoint does not exist,用于区别于普通的 404 | 2.14.0+ |
auth/login凭据无效 | 返回 401 | 2.14.0+ |
torrents/editTracker | 成功时固定返回 204 | 2.13.0+ |
客户端不要假设所有成功都是 200,也不要把所有 204 当成失败。以torrents/add为例,一个健壮的判断顺序是:先读状态码(202 表示部分待处理、409 表示全部失败),再解析响应体中的计数字段。
适配 API 变化:版本号对照 changelog
客户端在启动或每次部署后,应先用认证后的会话请求app/webapiVersion,把返回值与 WebAPI_Changelog.md 中你当前支持版本之后的条目逐一比对。以下是 changelog 中与「客户端兼容性」直接相关的破坏性变化(每条均可在 changelog 中按 PR 号核对):
- 2.16.0:
search/downloadTorrent与rss/setFeedRefreshInterval改为仅接受 POST;torrents/add新增seedMode(bool) 参数,且不再接受skip_checking参数。如果你的客户端还在发skip_checking,升级后该参数会被忽略,应切换到seedMode。 - 2.16.2:新增
rss/exportRules、rss/importRules(仅 POST);新增transfer/pauseSession、transfer/resumeSession;sync/maindata的server_state中新增session_state(bool) 字段——依赖server_state结构的代码要注意新字段的出现。 - 2.14.0:
torrents/add引入上表所述的计数字段与 202/409 状态码;不存在的端点开始返回Endpoint does not exist文案。 - 2.13.0:
torrents/editTracker的参数origUrl更名为url,旧参数名不再可用。 - 2.15.0:起可用 Basic auth 提供凭据(对旧客户端是可选的新路径,不是破坏项)。
排查方向可以由状态码反推:401 优先检查凭据或跨站来源;403 检查会话是否过期、是否在用 API Key 访问auth/*;405 Method Not Allowed 通常意味着该端点已改为仅 POST(对照 2.16.0/2.16.2 条目);收到Endpoint does not exist则说明端点被移除或更名,回 changelog 找对应版本的替换项。
限制与边界
- 公开端点只有
auth/login,其余全部依赖会话;用 API Key 认证时auth/*端点被禁止(403)。 - 会话 Cookie 有服务端超时,客户端需要处理 Cookie 失效后重新登录的分支。
- 各版本新增的参数(如
torrents/add的seedMode、sync/maindata的session_state)只在对应版本起可用,跨版本部署的客户端应以app/webapiVersion的返回值决定行为分支。
【免费下载链接】qBittorrentqBittorrent BitTorrent client项目地址: https://gitcode.com/GitHub_Trending/qb/qBittorrent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考