Fix: Use dynamic URLs for all frontend connections
- CSP: Allow WebSocket/HTTP connections to any domain (for production) - Nakama: Detect host/SSL from browser location instead of hardcoded localhost - WebSocket: Dynamic protocol/host detection for stream and watch sync - HLS/LLHLS/WebRTC: Dynamic URLs in live page and stream components - RTMP/SRT: Show actual domain in my-realms settings page - Forums: Use numeric forum ID for banner/title-color API calls 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e26fd346f3
commit
118629549e
9 changed files with 121 additions and 28 deletions
|
|
@ -29,7 +29,24 @@
|
|||
}
|
||||
|
||||
const STREAM_PORT = import.meta.env.VITE_STREAM_PORT || '8088';
|
||||
|
||||
const WEBRTC_PORT = import.meta.env.VITE_WEBRTC_PORT || '3333';
|
||||
|
||||
// Helper functions for dynamic host/protocol detection
|
||||
function getStreamHost() {
|
||||
if (!browser) return 'localhost';
|
||||
return window.location.hostname;
|
||||
}
|
||||
|
||||
function getStreamProtocol(secure = false) {
|
||||
if (!browser) return secure ? 'https' : 'http';
|
||||
return window.location.protocol === 'https:' ? 'https' : 'http';
|
||||
}
|
||||
|
||||
function getWsProtocol() {
|
||||
if (!browser) return 'ws';
|
||||
return window.location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
}
|
||||
|
||||
let player;
|
||||
let realm = null;
|
||||
let streamKey = '';
|
||||
|
|
@ -295,23 +312,28 @@
|
|||
}
|
||||
|
||||
const sources = [];
|
||||
|
||||
|
||||
if (streamKey) {
|
||||
// Dynamic URLs based on current page host/protocol
|
||||
const host = getStreamHost();
|
||||
const httpProto = getStreamProtocol();
|
||||
const wsProto = getWsProtocol();
|
||||
|
||||
// Add all sources - LLHLS first (default), then HLS, then WebRTC as fallback
|
||||
sources.push(
|
||||
{
|
||||
type: 'hls',
|
||||
file: `http://localhost:${STREAM_PORT}/app/${streamKey}/llhls.m3u8?token=${viewerToken}`,
|
||||
file: `${httpProto}://${host}:${STREAM_PORT}/app/${streamKey}/llhls.m3u8?token=${viewerToken}`,
|
||||
label: 'LLHLS (Low Latency)'
|
||||
},
|
||||
{
|
||||
type: 'hls',
|
||||
file: `http://localhost:${STREAM_PORT}/app/${streamKey}/ts:playlist.m3u8?token=${viewerToken}`,
|
||||
file: `${httpProto}://${host}:${STREAM_PORT}/app/${streamKey}/ts:playlist.m3u8?token=${viewerToken}`,
|
||||
label: 'HLS (Standard)'
|
||||
},
|
||||
{
|
||||
type: 'webrtc',
|
||||
file: `ws://localhost:3333/app/${streamKey}`,
|
||||
file: `${wsProto}://${host}:${WEBRTC_PORT}/app/${streamKey}`,
|
||||
label: 'WebRTC (Ultra Low Latency)'
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@
|
|||
const formData = new FormData();
|
||||
formData.append('banner', file);
|
||||
|
||||
const response = await fetch(`/api/forums/${$page.params.slug}/banner`, {
|
||||
const response = await fetch(`/api/forums/${forum.id}/banner`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: formData
|
||||
|
|
@ -274,7 +274,7 @@
|
|||
bannerError = '';
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/forums/${$page.params.slug}/banner`, {
|
||||
const response = await fetch(`/api/forums/${forum.id}/banner`, {
|
||||
method: 'DELETE',
|
||||
credentials: 'include'
|
||||
});
|
||||
|
|
@ -351,7 +351,7 @@
|
|||
bannerError = '';
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/forums/${$page.params.slug}/banner/position`, {
|
||||
const response = await fetch(`/api/forums/${forum.id}/banner/position`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
|
|
@ -396,7 +396,7 @@
|
|||
bannerError = '';
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/forums/${$page.params.slug}/title-color`, {
|
||||
const response = await fetch(`/api/forums/${forum.id}/title-color`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
<script>
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { browser } from '$app/environment';
|
||||
import { auth, isAuthenticated, isStreamer, isRestreamer, isUploader, isWatchCreator } from '$lib/stores/auth';
|
||||
import { siteSettings } from '$lib/stores/siteSettings';
|
||||
import { goto } from '$app/navigation';
|
||||
import { connectWebSocket, disconnectWebSocket } from '$lib/websocket';
|
||||
|
||||
// Dynamic host for streaming URLs (use current domain in production)
|
||||
$: streamHost = browser ? window.location.hostname : 'localhost';
|
||||
|
||||
let realms = [];
|
||||
let loading = true;
|
||||
let error = '';
|
||||
|
|
@ -2968,13 +2972,13 @@
|
|||
</div>
|
||||
<div class="stream-info-row">
|
||||
<span class="stream-info-label">RTMP URL:</span>
|
||||
<span class="stream-key">rtmp://localhost:1935/app/{realm.streamKey}</span>
|
||||
<button on:click={() => copyToClipboard(`rtmp://localhost:1935/app/${realm.streamKey}`)}>Copy</button>
|
||||
<span class="stream-key">rtmp://{streamHost}:1935/app/{realm.streamKey}</span>
|
||||
<button on:click={() => copyToClipboard(`rtmp://${streamHost}:1935/app/${realm.streamKey}`)}>Copy</button>
|
||||
</div>
|
||||
<div class="stream-info-row">
|
||||
<span class="stream-info-label">SRT URL:</span>
|
||||
<span class="stream-key">srt://localhost:9999?streamid={encodeURIComponent(`srt://localhost:9999/app/${realm.streamKey}`)}</span>
|
||||
<button on:click={() => copyToClipboard(`srt://localhost:9999?streamid=${encodeURIComponent(`srt://localhost:9999/app/${realm.streamKey}`)}`)}>Copy</button>
|
||||
<span class="stream-key">srt://{streamHost}:9999?streamid={encodeURIComponent(`srt://${streamHost}:9999/app/${realm.streamKey}`)}</span>
|
||||
<button on:click={() => copyToClipboard(`srt://${streamHost}:9999?streamid=${encodeURIComponent(`srt://${streamHost}:9999/app/${realm.streamKey}`)}`)}>Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue