feat: add CORS support, dynamic API_BASE for Netlify frontend, and netlify.toml
This commit is contained in:
parent
9fc9709f69
commit
55015d94d1
4 changed files with 39 additions and 4 deletions
8
netlify.toml
Normal file
8
netlify.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
[build]
|
||||||
|
publish = "public"
|
||||||
|
|
||||||
|
[[headers]]
|
||||||
|
for = "/*"
|
||||||
|
[headers.values]
|
||||||
|
X-Frame-Options = "DENY"
|
||||||
|
X-Content-Type-Options = "nosniff"
|
||||||
10
public/_redirects
Normal file
10
public/_redirects
Normal file
|
|
@ -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
|
||||||
|
|
@ -17,6 +17,14 @@
|
||||||
|
|
||||||
let selectedFiles = [];
|
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
|
// Toast
|
||||||
let toastTimeout;
|
let toastTimeout;
|
||||||
function showToast(msg) {
|
function showToast(msg) {
|
||||||
|
|
@ -221,7 +229,7 @@
|
||||||
// Fetch and display files
|
// Fetch and display files
|
||||||
async function fetchFiles() {
|
async function fetchFiles() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/files');
|
const res = await fetch(`${API_BASE}/files`);
|
||||||
const files = await res.json();
|
const files = await res.json();
|
||||||
fileList.innerHTML = '';
|
fileList.innerHTML = '';
|
||||||
|
|
||||||
|
|
@ -252,7 +260,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="file-actions">
|
<div class="file-actions">
|
||||||
<a href="/uploads/${encodeURIComponent(name)}" class="action-btn action-download" download>download</a>
|
<a href="${API_BASE}/uploads/${encodeURIComponent(name)}" class="action-btn action-download" download>download</a>
|
||||||
<button class="action-btn action-delete" onclick="deleteFile('${escapeHtml(name)}', this.closest('li'))">delete</button>
|
<button class="action-btn action-delete" onclick="deleteFile('${escapeHtml(name)}', this.closest('li'))">delete</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
@ -271,7 +279,7 @@
|
||||||
if (cardElement) cardElement.classList.add('deleting');
|
if (cardElement) cardElement.classList.add('deleting');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`/delete/${encodeURIComponent(filename)}`, { method: 'DELETE' });
|
const res = await fetch(`${API_BASE}/delete/${encodeURIComponent(filename)}`, { method: 'DELETE' });
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
showToast('file deleted');
|
showToast('file deleted');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
@ -343,7 +351,7 @@
|
||||||
showToast('upload failed');
|
showToast('upload failed');
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.open('POST', '/upload');
|
xhr.open('POST', `${API_BASE}/upload`);
|
||||||
xhr.send(formData);
|
xhr.send(formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,15 @@ const upload = multer({
|
||||||
});
|
});
|
||||||
|
|
||||||
// Middlewares
|
// 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.json());
|
||||||
app.use(express.static(publicDir));
|
app.use(express.static(publicDir));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue