68 lines
2.5 KiB
TypeScript
68 lines
2.5 KiB
TypeScript
const APP_BASE_PATH = import.meta.env.BASE_URL ?? '/';
|
|
|
|
/** Returns whether a hostname belongs to Dropbox domains that often need proxy support. */
|
|
function isDropboxHost(hostname: string): boolean {
|
|
const host = hostname.toLowerCase();
|
|
return host.endsWith('dropbox.com') || host.endsWith('dropboxusercontent.com');
|
|
}
|
|
|
|
/** Returns whether the URL already points at the local media proxy. */
|
|
function isLocalMediaProxyUrl(parsed: URL): boolean {
|
|
return parsed.origin === window.location.origin && parsed.pathname.toLowerCase().endsWith('/media_proxy.php');
|
|
}
|
|
|
|
/** Returns whether a direct radio stream URL should use the same-origin media proxy. */
|
|
export function shouldProxyRadioStreamUrl(streamUrl: string): boolean {
|
|
try {
|
|
const parsed = new URL(streamUrl);
|
|
if (isLocalMediaProxyUrl(parsed)) {
|
|
return false;
|
|
}
|
|
if (parsed.protocol === 'http:') return true;
|
|
if (parsed.protocol === 'https:' && isDropboxHost(parsed.hostname)) return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** Returns whether an arbitrary external media URL should be proxied before Web Audio playback. */
|
|
export function shouldProxyExternalMediaUrl(streamUrl: string): boolean {
|
|
try {
|
|
const parsed = new URL(streamUrl);
|
|
if (isLocalMediaProxyUrl(parsed)) {
|
|
return false;
|
|
}
|
|
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
return false;
|
|
}
|
|
return parsed.origin !== window.location.origin;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/** Builds the same-origin proxy URL for one remote media URL. */
|
|
export function getProxyUrlForMedia(streamUrl: string): string {
|
|
const normalizedBase = APP_BASE_PATH.endsWith('/') ? APP_BASE_PATH : `${APP_BASE_PATH}/`;
|
|
const proxy = new URL(`${normalizedBase}media_proxy.php`, window.location.origin);
|
|
proxy.searchParams.set('url', streamUrl);
|
|
return proxy.toString();
|
|
}
|
|
|
|
/** Appends a cache-buster to a radio playback URL to avoid stale stream sessions. */
|
|
export function freshRadioPlaybackUrl(streamUrl: string): string {
|
|
const playbackSource = shouldProxyRadioStreamUrl(streamUrl) ? getProxyUrlForMedia(streamUrl) : streamUrl;
|
|
try {
|
|
const parsed = new URL(playbackSource);
|
|
const hostname = parsed.hostname.toLowerCase();
|
|
if (hostname.endsWith('dropbox.com') || hostname.endsWith('dropboxusercontent.com')) {
|
|
return playbackSource;
|
|
}
|
|
} catch {
|
|
// Leave non-URL strings to the generic cache-buster behavior below.
|
|
}
|
|
const separator = playbackSource.includes('?') ? '&' : '?';
|
|
return `${playbackSource}${separator}chgrid_start=${Date.now()}`;
|
|
}
|