Initial commit: StreamFlow IPTV platform
This commit is contained in:
commit
73a8ae9ffd
1240 changed files with 278451 additions and 0 deletions
122
backend/routes/logo-proxy.js
Normal file
122
backend/routes/logo-proxy.js
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
const express = require('express');
|
||||
const axios = require('axios');
|
||||
const logger = require('../utils/logger');
|
||||
const { db } = require('../database/db');
|
||||
const path = require('path');
|
||||
const fs = require('fs').promises;
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Middleware to fix CORS for public image serving
|
||||
const fixImageCORS = (req, res, next) => {
|
||||
// Remove credentials header set by global CORS middleware
|
||||
res.removeHeader('Access-Control-Allow-Credentials');
|
||||
// Set proper CORS for public images
|
||||
res.set({
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type',
|
||||
'Cross-Origin-Resource-Policy': 'cross-origin'
|
||||
});
|
||||
next();
|
||||
};
|
||||
|
||||
// Handle OPTIONS preflight requests
|
||||
router.options('/', fixImageCORS, (req, res) => {
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
// Proxy external logos to handle CORS issues
|
||||
router.get('/', fixImageCORS, async (req, res) => {
|
||||
const { url } = req.query;
|
||||
|
||||
if (!url) {
|
||||
return res.status(400).json({ error: 'URL parameter is required' });
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if logo is cached
|
||||
const cached = await new Promise((resolve, reject) => {
|
||||
const query = 'SELECT logo_url, local_path FROM logo_cache WHERE logo_url = ? LIMIT 1';
|
||||
db.get(query, [url], (err, row) => {
|
||||
console.log(`[LogoProxy] SQL: ${query} with url="${url}"`);
|
||||
if (err) {
|
||||
console.error(`[LogoProxy] DB Error:`, err);
|
||||
reject(err);
|
||||
} else {
|
||||
console.log(`[LogoProxy] DB Result:`, row ? JSON.stringify(row) : 'null');
|
||||
resolve(row);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
console.log(`[LogoProxy] Cache lookup for ${url}: ${cached ? 'FOUND at ' + cached.local_path : 'NOT FOUND'}`);
|
||||
|
||||
// If cached, serve from disk
|
||||
if (cached && cached.local_path) {
|
||||
const cachedPath = cached.local_path;
|
||||
try {
|
||||
const fileData = await fs.readFile(cachedPath);
|
||||
const ext = path.extname(cachedPath).toLowerCase();
|
||||
const contentType = {
|
||||
'.png': 'image/png',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.gif': 'image/gif',
|
||||
'.webp': 'image/webp',
|
||||
'.svg': 'image/svg+xml'
|
||||
}[ext] || 'image/png';
|
||||
|
||||
res.set({
|
||||
'Content-Type': contentType,
|
||||
'Cache-Control': 'public, max-age=2592000' // Cache for 30 days
|
||||
});
|
||||
return res.send(fileData);
|
||||
} catch (err) {
|
||||
logger.warn('Cached logo file not found, fetching fresh:', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate URL
|
||||
const logoUrl = new URL(url);
|
||||
|
||||
// Fetch the image
|
||||
const response = await axios.get(url, {
|
||||
responseType: 'arraybuffer',
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
|
||||
'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
|
||||
'Accept-Language': 'en-US,en;q=0.9',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Pragma': 'no-cache'
|
||||
},
|
||||
maxRedirects: 5
|
||||
});
|
||||
|
||||
// Set appropriate headers
|
||||
const contentType = response.headers['content-type'] || 'image/png';
|
||||
res.set({
|
||||
'Content-Type': contentType,
|
||||
'Cache-Control': 'public, max-age=86400' // Cache for 24 hours
|
||||
});
|
||||
|
||||
// Send the image
|
||||
res.send(response.data);
|
||||
} catch (error) {
|
||||
logger.error('Logo proxy error:', {
|
||||
url,
|
||||
error: error.message,
|
||||
status: error.response?.status
|
||||
});
|
||||
|
||||
// Return a 404 or error response
|
||||
res.status(error.response?.status || 500).json({
|
||||
error: 'Failed to fetch logo',
|
||||
message: error.message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Loading…
Add table
Add a link
Reference in a new issue