From 4904717db0e0809128fab789902e3a22bc17f25b Mon Sep 17 00:00:00 2001 From: Bastien Wirtz Date: Sun, 28 Sep 2025 22:06:53 +0200 Subject: [PATCH] fix(smartcard): fix transmission service rework --- docs/customservices.md | 11 ++---- src/components/services/Transmission.vue | 47 +++++++++++++----------- src/mixins/service.js | 1 + 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/docs/customservices.md b/docs/customservices.md index 492e030..bb675c7 100644 --- a/docs/customservices.md +++ b/docs/customservices.md @@ -724,7 +724,8 @@ Displays Traefik. ## Transmission -This service displays the global upload and download rates, as well as the number of active torrents from your Transmission daemon. The service communicates with the Transmission RPC interface which needs to be accessible from the browser. Make sure to configure appropriate CORS headers if accessing from a different domain. +Displays the global upload and download rates, as well as the number of active torrents from your Transmission daemon. +The service communicates with the Transmission RPC interface which needs to be accessible from the browser. ```yaml - name: "Transmission" @@ -732,16 +733,12 @@ This service displays the global upload and download rates, as well as the numbe url: "http://192.168.1.2:9091" # Your Transmission web interface URL type: "Transmission" auth: "username:password" # Optional: HTTP Basic Auth - interval: 5000 # Optional: Interval for updating data (ms) + interval: 5000 # Optional: Interval for refreshing data (ms) target: "_blank" # Optional: HTML a tag target attribute ``` -**Configuration Options:** - -- `auth`: Optional HTTP Basic Authentication in "username:password" format -- `interval`: How often to refresh data in milliseconds - The service automatically handles Transmission's session management and CSRF protection. + ## Truenas Scale Displays TrueNAS version. diff --git a/src/components/services/Transmission.vue b/src/components/services/Transmission.vue index 81430e0..802c4f3 100644 --- a/src/components/services/Transmission.vue +++ b/src/components/services/Transmission.vue @@ -58,6 +58,7 @@ export default { count: null, error: null, sessionId: null, + retry: 0, }), computed: { downRate: function () { @@ -87,11 +88,6 @@ export default { transmissionRequest: async function (method) { const options = this.getRequestHeaders(method); - // Add HTTP Basic Auth if credentials are provided - if (this.item.auth) { - options.headers["Authorization"] = `Basic ${btoa(this.item.auth)}`; - } - // Add session ID header if we have one if (this.sessionId) { options.headers["X-Transmission-Session-Id"] = this.sessionId; @@ -101,21 +97,12 @@ export default { return await this.fetch("transmission/rpc", options); } catch (error) { // Handle Transmission's 409 session requirement - if (error.message.includes("409")) { - const sessionOptions = this.getRequestHeaders("session-get"); - - const sessionResponse = this.fetch( - "transmission/rpc", - sessionOptions, - ); - if (error.message.includes("409")) { - this.sessionId = sessionResponse.headers.get( - "X-Transmission-Session-Id", - ); - if (this.sessionId) { - options.headers["X-Transmission-Session-Id"] = this.sessionId; - return await this.fetch("transmission/rpc", options); - } + if (error.cause.status == 409 && this.retry <= 1) { + const sessionId = await this.getSession(); + if (sessionId) { + this.sessionId = sessionId; + this.retry++; + return this.transmissionRequest(method); } } console.error("Transmission RPC error:", error); @@ -123,13 +110,31 @@ export default { } }, getRequestHeaders: function (method) { - return { + const options = { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ method }), }; + + if (this.item.auth) { + options.headers["Authorization"] = `Basic ${btoa(this.item.auth)}`; + } + + return options; + }, + getSession: async function () { + try { + await this.fetch( + "transmission/rpc", + this.getRequestHeaders("session-get"), + ); + } catch (error) { + if (error.cause.status == 409) { + return error.cause.headers.get("X-Transmission-Session-Id"); + } + } }, getStats: async function () { try { diff --git a/src/mixins/service.js b/src/mixins/service.js index c15b5be..6d5c253 100644 --- a/src/mixins/service.js +++ b/src/mixins/service.js @@ -55,6 +55,7 @@ export default { if (!success) { throw new Error( `Fail to fetch ressource: (${response.status} error)`, + { cause: response }, ); }