From 8f8b5e37fc3c5dfab15cd2a3cb033c874118fd44 Mon Sep 17 00:00:00 2001 From: szbk Date: Wed, 3 Dec 2025 20:49:08 +0300 Subject: [PATCH] =?UTF-8?q?Resimler=20i=C3=A7in=20cache=20olu=C5=9Fturuldu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/routes/Movies.svelte | 4 +- client/src/routes/TvShows.svelte | 2 +- server/server.js | 86 ++++++++++++++------------------ 3 files changed, 41 insertions(+), 51 deletions(-) diff --git a/client/src/routes/Movies.svelte b/client/src/routes/Movies.svelte index 220261f..4fea477 100644 --- a/client/src/routes/Movies.svelte +++ b/client/src/routes/Movies.svelte @@ -335,13 +335,13 @@ async function loadMovies() { function posterUrl(movie) { if (!movie.poster) return null; const token = localStorage.getItem("token"); - return `${API}${movie.poster}?token=${token}&t=${Date.now()}`; + return `${API}${movie.poster}?token=${token}`; } function backdropUrl(movie) { if (!movie.backdrop) return null; const token = localStorage.getItem("token"); - return `${API}${movie.backdrop}?token=${token}&t=${Date.now()}`; + return `${API}${movie.backdrop}?token=${token}`; } async function refreshMovies() { diff --git a/client/src/routes/TvShows.svelte b/client/src/routes/TvShows.svelte index 665dea0..e7f836c 100644 --- a/client/src/routes/TvShows.svelte +++ b/client/src/routes/TvShows.svelte @@ -77,7 +77,7 @@ let filteredShows = []; function assetUrl(pathname) { if (!pathname) return null; const token = localStorage.getItem("token"); - return `${API}${pathname}?token=${token}&t=${Date.now()}`; + return `${API}${pathname}?token=${token}`; } function posterUrl(show) { diff --git a/server/server.js b/server/server.js index b67c768..0865dbb 100644 --- a/server/server.js +++ b/server/server.js @@ -1599,6 +1599,40 @@ function resolveTvDataAbsolute(relPath) { return resolved; } +function serveCachedFile(req, res, filePath, { maxAgeSeconds = 86400 } = {}) { + if (!fs.existsSync(filePath)) { + return res.status(404).send("Dosya bulunamadı"); + } + let stats; + try { + stats = fs.statSync(filePath); + } catch (err) { + return res.status(500).send("Dosya okunamadı"); + } + const mtime = stats.mtimeMs; + const etag = `"${stats.size}-${Number(mtime).toString(16)}"`; + + const ifNoneMatch = req.headers["if-none-match"]; + const ifModifiedSince = req.headers["if-modified-since"] + ? new Date(req.headers["if-modified-since"]).getTime() + : null; + + if (ifNoneMatch && ifNoneMatch === etag) { + return res.status(304).end(); + } + if (ifModifiedSince && ifModifiedSince >= mtime) { + return res.status(304).end(); + } + + res.setHeader( + "Cache-Control", + `public, max-age=${maxAgeSeconds}, stale-while-revalidate=${maxAgeSeconds}` + ); + res.setHeader("ETag", etag); + res.setHeader("Last-Modified", new Date(mtime).toUTCString()); + return res.sendFile(filePath); +} + function resolveYoutubeDataAbsolute(relPath) { const normalized = sanitizeRelative(relPath); const resolved = path.resolve(YT_DATA_ROOT, normalized); @@ -4312,72 +4346,28 @@ app.get("/thumbnails/:path(*)", requireAuth, (req, res) => { const relThumb = req.params.path || ""; const fullPath = resolveThumbnailAbsolute(relThumb); if (!fullPath) return res.status(400).send("Geçersiz thumbnail yolu"); - if (!fs.existsSync(fullPath)) return res.status(404).send("Thumbnail yok"); - res.sendFile(fullPath); + return serveCachedFile(req, res, fullPath, { maxAgeSeconds: 60 * 60 * 24 }); }); app.get("/movie-data/:path(*)", requireAuth, (req, res) => { const relPath = req.params.path || ""; const fullPath = resolveMovieDataAbsolute(relPath); if (!fullPath) return res.status(400).send("Geçersiz movie data yolu"); - if (!fs.existsSync(fullPath)) return res.status(404).send("Dosya bulunamadı"); - - // Cache kontrolü için dosya değişim zamanını ekle - const stats = fs.statSync(fullPath); - const lastModified = stats.mtime.getTime(); - - // Eğer client If-Modified-Since header gönderdiyse kontrol et - const ifModifiedSince = req.headers['if-modified-since']; - if (ifModifiedSince) { - const clientTime = new Date(ifModifiedSince).getTime(); - if (clientTime >= lastModified) { - return res.status(304).end(); // Not Modified - } - } - - // Cache-Control header'larını ayarla - res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); - res.setHeader('Pragma', 'no-cache'); - res.setHeader('Expires', '0'); - res.setHeader('Last-Modified', new Date(lastModified).toUTCString()); - - res.sendFile(fullPath); + return serveCachedFile(req, res, fullPath, { maxAgeSeconds: 60 * 60 * 24 }); }); app.get("/yt-data/:path(*)", requireAuth, (req, res) => { const relPath = req.params.path || ""; const fullPath = resolveYoutubeDataAbsolute(relPath); if (!fullPath) return res.status(400).send("Geçersiz yt data yolu"); - if (!fs.existsSync(fullPath)) return res.status(404).send("Dosya bulunamadı"); - res.sendFile(fullPath); + return serveCachedFile(req, res, fullPath, { maxAgeSeconds: 60 * 60 * 24 }); }); app.get("/tv-data/:path(*)", requireAuth, (req, res) => { const relPath = req.params.path || ""; const fullPath = resolveTvDataAbsolute(relPath); if (!fullPath) return res.status(400).send("Geçersiz tv data yolu"); - if (!fs.existsSync(fullPath)) return res.status(404).send("Dosya bulunamadı"); - - // Cache kontrolü için dosya değişim zamanını ekle - const stats = fs.statSync(fullPath); - const lastModified = stats.mtime.getTime(); - - // Eğer client If-Modified-Since header gönderdiyse kontrol et - const ifModifiedSince = req.headers['if-modified-since']; - if (ifModifiedSince) { - const clientTime = new Date(ifModifiedSince).getTime(); - if (clientTime >= lastModified) { - return res.status(304).end(); // Not Modified - } - } - - // Cache-Control header'larını ayarla - res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); - res.setHeader('Pragma', 'no-cache'); - res.setHeader('Expires', '0'); - res.setHeader('Last-Modified', new Date(lastModified).toUTCString()); - - res.sendFile(fullPath); + return serveCachedFile(req, res, fullPath, { maxAgeSeconds: 60 * 60 * 24 }); }); // --- Torrentleri listele ---