From 65755a08aaceb2b412929e5fd852d2755944b730 Mon Sep 17 00:00:00 2001 From: Jason Fischer Date: Wed, 28 Sep 2022 09:55:18 -0700 Subject: [PATCH] Better login strategy for qbittorrent proxy - Additional logging in httpProxy --- src/utils/proxy/http.js | 22 ++++++++++++++++++--- src/widgets/qbittorrent/proxy.js | 34 +++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/src/utils/proxy/http.js b/src/utils/proxy/http.js index feed71ddf..4eba83f32 100644 --- a/src/utils/proxy/http.js +++ b/src/utils/proxy/http.js @@ -4,6 +4,10 @@ import { http, https } from "follow-redirects"; import { addCookieToJar, setCookieHeader } from "./cookie-jar"; +import createLogger from "utils/logger"; + +const logger = createLogger("httpProxy"); + function addCookieHandler(url, params) { setCookieHeader(url, params); @@ -70,18 +74,30 @@ export function httpRequest(url, params) { }); } -export function httpProxy(url, params = {}) { +export async function httpProxy(url, params = {}) { const constructedUrl = new URL(url); + let request = null; if (constructedUrl.protocol === "https:") { const httpsAgent = new https.Agent({ rejectUnauthorized: false, }); - return httpsRequest(constructedUrl, { + request = httpsRequest(constructedUrl, { agent: httpsAgent, ...params, }); + } else { + request = httpRequest(constructedUrl, params); + } + + try { + const [status, contentType, data, responseHeaders] = await request; + return [status, contentType, data, responseHeaders]; + } + catch (err) { + logger.error("Error calling %s//%s%s...", url.protocol, url.hostname, url.pathname); + logger.error(err); + return [500, "application/json", { error: "Unexpected error" }, null]; } - return httpRequest(constructedUrl, params); } diff --git a/src/widgets/qbittorrent/proxy.js b/src/widgets/qbittorrent/proxy.js index da4b9a7f3..14271b656 100644 --- a/src/widgets/qbittorrent/proxy.js +++ b/src/widgets/qbittorrent/proxy.js @@ -2,8 +2,12 @@ import { formatApiCall } from "utils/proxy/api-helpers"; import { addCookieToJar, setCookieHeader } from "utils/proxy/cookie-jar"; import { httpProxy } from "utils/proxy/http"; import getServiceWidget from "utils/config/service-helpers"; +import createLogger from "utils/logger"; + +const logger = createLogger("qbittorrentProxyHandler"); async function login(widget, params) { + logger.debug("qBittorrent is rejecting the request, logging in."); const loginUrl = new URL(`${widget.url}/api/v2/auth/login`).toString(); const loginBody = `username=${encodeURI(widget.username)}&password=${encodeURI(widget.password)}`; @@ -14,46 +18,54 @@ async function login(widget, params) { headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: loginBody, }) - .then(async (response) => { - addCookieToJar(loginUrl, response.headers); - setCookieHeader(loginUrl, params); - const data = await response.text(); - return [response.status, data]; - }) - .catch((err) => [500, err]); + .then(async (response) => { + addCookieToJar(loginUrl, response.headers); + setCookieHeader(loginUrl, params); + const data = await response.text(); + return [response.status, data]; + }) + .catch((err) => [500, err]); } export default async function qbittorrentProxyHandler(req, res) { const { group, service, endpoint } = req.query; if (!group || !service) { + logger.debug("Invalid or missing service '%s' or group '%s'", service, group); return res.status(400).json({ error: "Invalid proxy service type" }); } const widget = await getServiceWidget(group, service); if (!widget) { + logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group); return res.status(400).json({ error: "Invalid proxy service type" }); } const url = new URL(formatApiCall("{url}/api/v2/{endpoint}", { endpoint, ...widget })); const params = { method: "GET", headers: {} }; - setCookieHeader(url, params); - if (!params.headers.Cookie) { - const [status, data] = await login(widget, params); + let [status, contentType, data] = await httpProxy(url, params); + if (status === 403) { + [status, data] = await login(widget, params); if (status !== 200) { + logger.error("HTTP %d logging in to qBittorrent. Data: %s", status, data); return res.status(status).end(data); } if (data.toString() !== "Ok.") { + logger.error("Error logging in to qBittorrent: Data: %s", data); return res.status(401).end(data); } } - const [status, contentType, data] = await httpProxy(url, params); + [status, contentType, data] = await httpProxy(url, params); + + if (status !== 200) { + logger.error("HTTP %d getting data from qBittorrent. Data: %s", status, data); + } if (contentType) res.setHeader("Content-Type", contentType); return res.status(status).send(data);