From 84c7e5126977ca2f58ccf3caa46c88eaf670c5dd Mon Sep 17 00:00:00 2001 From: headscarf737 <249737766+headscarf737@users.noreply.github.com> Date: Tue, 21 Jul 2026 18:14:39 +0200 Subject: [PATCH] Chore: simplify qbittorrent api key handling (#6888) Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com> --- src/widgets/qbittorrent/proxy.js | 11 +++-------- src/widgets/qbittorrent/proxy.test.js | 17 +++++++---------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/widgets/qbittorrent/proxy.js b/src/widgets/qbittorrent/proxy.js index c959605a7..b7a6235c3 100644 --- a/src/widgets/qbittorrent/proxy.js +++ b/src/widgets/qbittorrent/proxy.js @@ -9,18 +9,12 @@ async function login(widget) { logger.debug("qBittorrent is rejecting the request, logging in."); const loginUrl = new URL(`${widget.url}/api/v2/auth/login`).toString(); const loginBody = `username=${encodeURIComponent(widget.username)}&password=${encodeURIComponent(widget.password)}`; - const loginKey = `${widget.key}`; const loginParams = { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: loginBody, }; - if (widget.key) { - loginParams.headers.Authorization = `Bearer ${loginKey}`; - } else if (widget.username && widget.password) { - loginParams.body = loginBody; - } - const [status, contentType, data] = await httpProxy(loginUrl, loginParams); return [status, data]; } @@ -42,9 +36,10 @@ export default async function qbittorrentProxyHandler(req, res) { const url = new URL(formatApiCall("{url}/api/v2/{endpoint}", { endpoint, ...widget })); const params = { method: "GET", headers: {} }; + if (widget.key) params.headers.Authorization = `Bearer ${widget.key}`; let [status, contentType, data] = await httpProxy(url, params); - if (status === 403) { + if (status === 403 && !widget.key) { [status, data] = await login(widget); if (![200, 204].includes(status)) { diff --git a/src/widgets/qbittorrent/proxy.test.js b/src/widgets/qbittorrent/proxy.test.js index f9ee82ffc..9b87a775b 100644 --- a/src/widgets/qbittorrent/proxy.test.js +++ b/src/widgets/qbittorrent/proxy.test.js @@ -84,23 +84,20 @@ describe("widgets/qbittorrent/proxy", () => { expect(res.body).toEqual(Buffer.from("Denied")); }); - it("supports API keys by including them in the Authorization header and not the body", async () => { + it("uses an API key on the WebAPI request without attempting login", async () => { getServiceWidget.mockResolvedValue({ url: "http://qb", key: "abc123" }); - httpProxy - .mockResolvedValueOnce([403, "application/json", Buffer.from("nope")]) - .mockResolvedValueOnce([200, "text/plain", Buffer.from("Ok.")]) - .mockResolvedValueOnce([200, "application/json", Buffer.from("data")]); + httpProxy.mockResolvedValueOnce([403, "application/json", Buffer.from("nope")]); const req = { query: { group: "g", service: "svc", endpoint: "torrents/info", index: "0" } }; const res = createMockRes(); await qbittorrentProxyHandler(req, res); - expect(httpProxy).toHaveBeenCalledTimes(3); - expect(httpProxy.mock.calls[1][0]).toBe("http://qb/api/v2/auth/login"); - expect(httpProxy.mock.calls[1][1].headers.Authorization).toBe("Bearer abc123"); - expect(res.statusCode).toBe(200); - expect(res.body).toEqual(Buffer.from("data")); + expect(httpProxy).toHaveBeenCalledTimes(1); + expect(httpProxy.mock.calls[0][0].toString()).toBe("http://qb/api/v2/torrents/info"); + expect(httpProxy.mock.calls[0][1].headers.Authorization).toBe("Bearer abc123"); + expect(res.statusCode).toBe(403); + expect(res.body).toEqual(Buffer.from("nope")); }); });