diff --git a/p/server.js b/p/server.js index c388e6c1..94971e66 100644 --- a/p/server.js +++ b/p/server.js @@ -7,8 +7,7 @@ const { Readable } = require("node:stream"); const URL_WHITELIST = [ "i.ytimg.com", "yt3.googleusercontent.com", - "cdn.glitch.global", - "cdn.glitch.me", + "cdn.glitch.global", "cdn.glitch.me", "cdn.statically.io", "site-assets.fontawesome.com", "fonts.gstatic.com", @@ -40,8 +39,8 @@ const URL_WHITELIST = [ const app = express(); -app.use(express.json()); // for parsing application/json -app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); app.use(function (req, res, next) { console.log(`=> ${req.method} ${req.originalUrl.slice(1)}`); @@ -50,9 +49,8 @@ app.use(function (req, res, next) { app.use(function (_req, res, next) { res.header("Access-Control-Allow-Origin", "*"); - res.setHeader("Cache-Control", "public, max-age=864000"); // cache header + res.setHeader("Cache-Control", "public, max-age=864000"); res.setHeader("poketube-cacher", "PROXY_FILES"); - next(); }); @@ -61,33 +59,36 @@ app.use(function (_req, res, next) { * @param {express.Response} res */ const proxy = async (req, res) => { - const { fetch } = await import("undici") - res.setHeader("Cache-Control", "public, max-age=864000"); // cache header + const { fetch } = await import("undici"); + res.setHeader("Cache-Control", "public, max-age=864000"); try { - let url; + let rawUrl = "https://" + req.originalUrl.slice(8); + if (rawUrl.includes("cdn.glitch.global")) { + rawUrl = rawUrl.replace("cdn.glitch.global", "cdn.glitch.me"); + } + + let url; try { - url = new URL("https://" + req.originalUrl.slice(8)); + url = new URL(rawUrl); } catch (e) { console.log("==> Cannot parse URL: " + e); return res.status(400).send("Malformed URL"); } - // Sanity check, to avoid being used as an open proxy - if (!URL_WHITELIST.includes(url.host)) { + if (!URL_WHITELIST.includes(url.host) && !rawUrl.includes("cdn.glitch.me")) { console.log(`==> Refusing to proxy host ${url.host}`); res.status(401).send(`Hostname '${url.host}' is not permitted`); return; } console.log(`==> Proxying request`); - - let f = await fetch(url + `?cachefixer=${btoa(Date.now())}`, { + let f = await fetch(rawUrl + `?cachefixer=${btoa(Date.now())}`, { method: req.method, }); -Readable.fromWeb(f.body).pipe(res); + Readable.fromWeb(f.body).pipe(res); } catch (e) { console.log(`==> Error: ${e}`); res.status(500).send("Internal server error"); @@ -101,62 +102,51 @@ const listener = (req, res) => { app.get("/", (req, res) => { var json = { status: "200", - version: "1.3.1", + version: "1.3.2", URL_WHITELIST, cache: "max-age-864000", }; - res.json(json); }); const apiUrls = [ "https://returnyoutubedislikeapi.com/votes?videoId=", "https://prod-poketube.testing.poketube.fun/api?v=", - "https://ipv6-t.poketube.fun/api?v=" + "https://ipv6-t.poketube.fun/api?v=", ]; -// Define a cache object const cache = {}; app.get("/api", async (req, res) => { -const { fetch } = await import("undici") + const { fetch } = await import("undici"); try { const cacheKey = req.query.v; - // Check if the result is already cached if (cache[cacheKey] && Date.now() - cache[cacheKey].timestamp < 3600000) { - // If the cached result is less than 1 hour old, return it - const cachedData = cache[cacheKey].data; - const cachedDate = new Date(cache[cacheKey].timestamp); - return res.json(cachedData); + return res.json(cache[cacheKey].data); } - // Initialize an array to store errors when trying different URLs const errors = []; - for (const apiUrl of apiUrls) { try { - // Fetch data from the current URL - const engagement = await fetch(apiUrl + req.query.v).then((res) => res.json()); + const engagement = await fetch(apiUrl + req.query.v).then((res) => + res.json() + ); - // Cache the result for future requests cache[cacheKey] = { data: engagement, timestamp: Date.now(), }; res.json(engagement); - return; // Exit the loop if successful + return; } catch (err) { - // Log the error for this URL and continue to the next URL console.log(`Error fetching data from ${apiUrl}: ${err.message}`); errors.push(err.message); - return ""; } } - // If all URLs fail, return an error response res.status(500).json({ error: "All API endpoints failed", errors }); } catch (err) { console.log(err); @@ -164,15 +154,13 @@ const { fetch } = await import("undici") }); app.get("/bangs", async (req, res) => { - - let f = await fetch("https://lite.duckduckgo.com/lite/?q=" + req.query.q, { - method: req.method, - }); + let f = await fetch("https://lite.duckduckgo.com/lite/?q=" + req.query.q, { + method: req.method, + }); - res.redirect(f); - + res.redirect(f); }); app.all("/*", listener); -app.listen(6014, () => console.log("Listening on 0.0.0.0:6014")); \ No newline at end of file +app.listen(6014, () => console.log("Listening on 0.0.0.0:6014"));