diff --git a/groups/RODA/index.html b/groups/RODA/index.html index 87c4cbc..1fd1020 100644 --- a/groups/RODA/index.html +++ b/groups/RODA/index.html @@ -1541,6 +1541,11 @@ return rows; } + function shouldUseLocalDashboardProxy() { + const hostname = window.location.hostname; + return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === ''; + } + async function fetchDashboardData() { const grid = document.getElementById('riset-grid'); if (grid) { @@ -1557,10 +1562,10 @@ ? window.APP_CONFIG.dashboardProxyTemplates.filter(Boolean) : []; - // Sumber utama: endpoint proxy lokal (server.js fetch server-side, tanpa CORS). - const proxyServers = [() => '/api/dashboard']; + // Endpoint server.js hanya ada saat development lokal. + const proxyServers = shouldUseLocalDashboardProxy() ? [() => '/api/dashboard'] : []; - // Fallback: proxy publik (butuh targetUrl untuk membangun URL). + // Deployment static memakai proxy publik karena tidak menjalankan server.js. if (targetUrl) { proxyTemplates.forEach((template) => { proxyServers.push((url) => template @@ -1570,6 +1575,10 @@ }); } + if (!proxyServers.length) { + throw new Error('DASHBOARD_PROXY_NOT_CONFIGURED'); + } + let lastError = null; for (const getProxyUrl of proxyServers) { diff --git a/netlify.toml b/netlify.toml index 2a8fe6c..0cab1ff 100644 --- a/netlify.toml +++ b/netlify.toml @@ -4,12 +4,3 @@ [build.environment] NODE_VERSION = "22" - -[functions] - directory = "netlify/functions" - node_bundler = "esbuild" - -[[redirects]] - from = "/api/dashboard" - to = "/.netlify/functions/dashboard" - status = 200 diff --git a/netlify/functions/dashboard.js b/netlify/functions/dashboard.js deleted file mode 100644 index c9fad0d..0000000 --- a/netlify/functions/dashboard.js +++ /dev/null @@ -1,68 +0,0 @@ -const DEFAULT_DASHBOARD_URL = 'https://dashboard.informatika.untan.ac.id/index.php?penelitian'; -const CACHE_TTL_MS = 5 * 60 * 1000; - -let dashboardCache = { - html: '', - timestamp: 0, -}; - -function getDashboardUrl() { - return process.env.DASHBOARD_TARGET_URL || DEFAULT_DASHBOARD_URL; -} - -function response(statusCode, body, extraHeaders = {}) { - return { - statusCode, - headers: { - 'Content-Type': 'text/html; charset=utf-8', - 'Cache-Control': 'public, max-age=60, stale-while-revalidate=300', - ...extraHeaders, - }, - body, - }; -} - -exports.handler = async () => { - const now = Date.now(); - - if (dashboardCache.html && now - dashboardCache.timestamp < CACHE_TTL_MS) { - return response(200, dashboardCache.html, { 'X-Cache': 'HIT' }); - } - - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 12000); - - try { - const dashboardResponse = await fetch(getDashboardUrl(), { - signal: controller.signal, - headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36', - }, - }); - - if (!dashboardResponse.ok) { - throw new Error(`HTTP_ERROR_${dashboardResponse.status}`); - } - - const html = await dashboardResponse.text(); - dashboardCache = { html, timestamp: Date.now() }; - - return response(200, html, { 'X-Cache': 'MISS' }); - } catch (error) { - if (dashboardCache.html) { - return response(200, dashboardCache.html, { 'X-Cache': 'STALE' }); - } - - return { - statusCode: 502, - headers: { - 'Content-Type': 'text/plain; charset=utf-8', - }, - body: error && error.name === 'AbortError' - ? 'DASHBOARD_FETCH_TIMEOUT' - : 'DASHBOARD_FETCH_FAILED', - }; - } finally { - clearTimeout(timeoutId); - } -};