Browse Source

Cache Pyload widget login sessionId, refactor

Michael Shamoon 2 years ago
parent
commit
8b2b8d7b35
3 changed files with 70 additions and 24 deletions
  1. 13 5
      src/widgets/pyload/component.jsx
  2. 50 18
      src/widgets/pyload/proxy.js
  3. 7 1
      src/widgets/pyload/widget.js

+ 13 - 5
src/widgets/pyload/component.jsx

@@ -7,15 +7,23 @@ import useWidgetAPI from "utils/proxy/use-widget-api";
 export default function Component({ service }) {
 export default function Component({ service }) {
   const { t } = useTranslation();
   const { t } = useTranslation();
   const { widget } = service;
   const { widget } = service;
-  const { data: pyloadData, error: pyloadError } = useWidgetAPI(
-    widget,
-    "statusServer",
-  );
+  const { data: pyloadData, error: pyloadError } = useWidgetAPI(widget, "status");
 
 
-  if (pyloadError || !pyloadData) {
+  if (pyloadError || pyloadData?.error) {
     return <Container error={t("widget.api_error")} />;
     return <Container error={t("widget.api_error")} />;
   }
   }
 
 
+  if (!pyloadData) {
+    return (
+      <Container service={service}>
+        <Block label="pyload.speed" />
+        <Block label="pyload.active" />
+        <Block label="pyload.queue" />
+        <Block label="pyload.total" />
+      </Container>
+    );
+  }
+
   return (
   return (
     <Container service={service}>
     <Container service={service}>
       <Block label="pyload.speed" value={t("common.bitrate", { value: pyloadData.speed })} />
       <Block label="pyload.speed" value={t("common.bitrate", { value: pyloadData.speed })} />

+ 50 - 18
src/widgets/pyload/proxy.js

@@ -1,6 +1,36 @@
+import cache from "memory-cache";
+
 import getServiceWidget from "utils/config/service-helpers";
 import getServiceWidget from "utils/config/service-helpers";
 import { formatApiCall } from "utils/proxy/api-helpers";
 import { formatApiCall } from "utils/proxy/api-helpers";
 import widgets from "widgets/widgets";
 import widgets from "widgets/widgets";
+import createLogger from "utils/logger";
+
+const proxyName = 'pyloadProxyHandler';
+const logger = createLogger(proxyName);
+const sessionCacheKey = `${proxyName}__sessionId`;
+
+async function fetchFromPyloadAPI(url, sessionId, params) {
+  const options = {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/x-www-form-urlencoded",
+    },
+  };
+
+  if (params) {
+    options.body = Object.keys(params).map(k => `${k}=${params[k]}`).join('&');
+  } else {
+    options.body = `session=${sessionId}`
+  }
+  
+  return fetch(url, options).then((response) => response.json());
+}
+
+async function login(loginUrl, username, password) {
+  const sessionId = await fetchFromPyloadAPI(loginUrl, null, { username, password })
+  cache.put(sessionCacheKey, sessionId);
+  return sessionId;
+}
 
 
 export default async function pyloadProxyHandler(req, res) {
 export default async function pyloadProxyHandler(req, res) {
   const { group, service, endpoint } = req.query;
   const { group, service, endpoint } = req.query;
@@ -12,27 +42,29 @@ export default async function pyloadProxyHandler(req, res) {
       const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
       const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));
       const loginUrl = `${widget.url}/api/login`;
       const loginUrl = `${widget.url}/api/login`;
 
 
-      // Pyload api does not support argument passing as JSON.
-      const sessionId = await fetch(loginUrl, {
-        method: "POST",
-        // Empty passwords are supported.
-        body: `username=${widget.username}&password=${widget.password ?? ''}`,
-        headers: {
-          "Content-Type": "application/x-www-form-urlencoded",
-        },
-      }).then((response) => response.json());
-
-      const apiResponse = await fetch(url, {
-        method: "POST",
-        body: `session=${sessionId}`,
-        headers: {
-          "Content-Type": "application/x-www-form-urlencoded",
-        },
-      }).then((response) => response.json());
+      let sessionId = cache.get(sessionCacheKey);
+
+      if (!sessionId) {
+        sessionId = await login(loginUrl, widget.username, widget.password);
+      }
 
 
+      let apiResponse = await fetchFromPyloadAPI(url, sessionId);
+
+      if (apiResponse?.error === 'Forbidden') {
+        logger.debug("Failed to retrieve data from Pyload API, login and re-try");
+        cache.del(sessionCacheKey);
+        sessionId = await login(loginUrl, widget.username, widget.password);
+        apiResponse = await fetchFromPyloadAPI(url, sessionId);
+      }
+      
+      if (apiResponse?.error) {
+        return res.status(500).send(apiResponse);
+      }
+      cache.del(sessionCacheKey);
+      
       return res.send(apiResponse);
       return res.send(apiResponse);
     }
     }
   }
   }
 
 
   return res.status(400).json({ error: "Invalid proxy service type" });
   return res.status(400).json({ error: "Invalid proxy service type" });
-}
+}

+ 7 - 1
src/widgets/pyload/widget.js

@@ -3,6 +3,12 @@ import pyloadProxyHandler from "./proxy";
 const widget = {
 const widget = {
   api: "{url}/api/{endpoint}",
   api: "{url}/api/{endpoint}",
   proxyHandler: pyloadProxyHandler,
   proxyHandler: pyloadProxyHandler,
-};
+
+  mappings: {
+    "status": {
+      endpoint: "statusServer",
+    }
+  }
+}
 
 
 export default widget;
 export default widget;