diff --git a/docker/cors-proxy.conf b/docker/cors-proxy.conf new file mode 100644 index 0000000..d86f552 --- /dev/null +++ b/docker/cors-proxy.conf @@ -0,0 +1,33 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 80; + server_name localhost; + + location / { + # Add CORS headers + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' '*' always; + + # Proxy configuration + proxy_pass $arg_url; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # Fix for TIDAL + proxy_set_header Origin "https://listen.tidal.com"; + proxy_set_header Referer "https://listen.tidal.com/"; + + # Increase timeouts for audio + proxy_connect_timeout 60s; + proxy_send_timeout 300s; + proxy_read_timeout 300s; + } + } +} \ No newline at end of file diff --git a/docker/cors-proxy.yml b/docker/cors-proxy.yml new file mode 100644 index 0000000..2f58427 --- /dev/null +++ b/docker/cors-proxy.yml @@ -0,0 +1,16 @@ +version: '3.8' + +services: + cors-proxy: + image: nginx:alpine + container_name: cors-proxy + restart: unless-stopped + ports: + - '8081:80' + volumes: + - ./cors-proxy.conf:/etc/nginx/nginx.conf:ro + healthcheck: + test: ['CMD', 'wget', '-q', '--spider', 'http://localhost/'] + interval: 30s + timeout: 10s + retries: 3 diff --git a/js/proxy-utils.js b/js/proxy-utils.js index 5311fc9..4361d61 100644 --- a/js/proxy-utils.js +++ b/js/proxy-utils.js @@ -1,9 +1,12 @@ const PROXIES = [ + { url: 'http://your-nas-ip:8081/', param: 'url=' }, // Local proxy - change to your NAS IP { url: 'https://audio-proxy.binimum.org/proxy-audio', param: 'url=' }, { url: 'https://corsproxy.io/?', param: '' }, + { url: 'https://api.allorigins.win/raw?url=', param: '' }, ]; let proxyIndex = 0; +let failedProxies = new Set(); export const getProxyUrl = (url) => { if (!url || typeof url !== 'string') return url; @@ -11,10 +14,32 @@ export const getProxyUrl = (url) => { if (url.startsWith('blob:')) return url; if (url.startsWith('https://audio-proxy.binimum.org/')) return url; - const proxy = PROXIES[proxyIndex % PROXIES.length]; + // Find first working proxy + for (let i = 0; i < PROXIES.length; i++) { + const proxy = PROXIES[(proxyIndex + i) % PROXIES.length]; + if (!failedProxies.has(proxy.url)) { + proxyIndex = (proxyIndex + i) % PROXIES.length; + return `${proxy.url}${proxy.param}${encodeURIComponent(url)}`; + } + } + + // All proxies failed, reset and try first one + failedProxies.clear(); + const proxy = PROXIES[0]; return `${proxy.url}${proxy.param}${encodeURIComponent(url)}`; }; +export const markProxyFailed = (url) => { + for (const proxy of PROXIES) { + if (url.includes(proxy.url)) { + failedProxies.add(proxy.url); + console.warn(`Proxy ${proxy.url} marked as failed, rotating...`); + rotateProxy(); + break; + } + } +}; + export const rotateProxy = () => { proxyIndex = (proxyIndex + 1) % PROXIES.length; };