From 55015d94d1cdf1e7673683652e5ed9573f911a66 Mon Sep 17 00:00:00 2001 From: oiupoyt Date: Sat, 12 Sep 2026 09:55:55 +0530 Subject: [PATCH] feat: add CORS support, dynamic API_BASE for Netlify frontend, and netlify.toml --- netlify.toml | 8 ++++++++ public/_redirects | 10 ++++++++++ public/js/app.js | 16 ++++++++++++---- server.js | 9 +++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 netlify.toml create mode 100644 public/_redirects diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..80c46da --- /dev/null +++ b/netlify.toml @@ -0,0 +1,8 @@ +[build] + publish = "public" + +[[headers]] + for = "/*" + [headers.values] + X-Frame-Options = "DENY" + X-Content-Type-Options = "nosniff" diff --git a/public/_redirects b/public/_redirects new file mode 100644 index 0000000..fbc9778 --- /dev/null +++ b/public/_redirects @@ -0,0 +1,10 @@ +# Netlify redirects file +# To proxy API requests through Netlify (bypassing mixed content & CORS), +# replace YOUR_BACKEND_URL with your Termux backend URL (e.g., Cloudflare Tunnel / ngrok URL): +# /files https://YOUR_BACKEND_URL/files 200 +# /upload https://YOUR_BACKEND_URL/upload 200 +# /uploads/* https://YOUR_BACKEND_URL/uploads/:splat 200 +# /delete/* https://YOUR_BACKEND_URL/delete/:splat 200 + +# SPA fallback rule +/* /index.html 200 diff --git a/public/js/app.js b/public/js/app.js index e44d35c..ef1bccb 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -17,6 +17,14 @@ let selectedFiles = []; + // API Base configuration for remote frontend (Netlify) or local hosting + const urlParams = new URLSearchParams(window.location.search); + if (urlParams.has('api')) { + const customApi = urlParams.get('api').replace(/\/+$/, ''); + localStorage.setItem('katdrop_api', customApi); + } + const API_BASE = window.KATDROP_API || localStorage.getItem('katdrop_api') || ''; + // Toast let toastTimeout; function showToast(msg) { @@ -221,7 +229,7 @@ // Fetch and display files async function fetchFiles() { try { - const res = await fetch('/files'); + const res = await fetch(`${API_BASE}/files`); const files = await res.json(); fileList.innerHTML = ''; @@ -252,7 +260,7 @@
- download + download
`; @@ -271,7 +279,7 @@ if (cardElement) cardElement.classList.add('deleting'); try { - const res = await fetch(`/delete/${encodeURIComponent(filename)}`, { method: 'DELETE' }); + const res = await fetch(`${API_BASE}/delete/${encodeURIComponent(filename)}`, { method: 'DELETE' }); if (res.ok) { showToast('file deleted'); setTimeout(() => { @@ -343,7 +351,7 @@ showToast('upload failed'); }; - xhr.open('POST', '/upload'); + xhr.open('POST', `${API_BASE}/upload`); xhr.send(formData); } diff --git a/server.js b/server.js index 1f9429b..e61b698 100644 --- a/server.js +++ b/server.js @@ -92,6 +92,15 @@ const upload = multer({ }); // Middlewares +app.use((req, res, next) => { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS'); + res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); + if (req.method === 'OPTIONS') { + return res.sendStatus(200); + } + next(); +}); app.use(express.json()); app.use(express.static(publicDir));