fix(frontend): prefix auth API requests with VITE_PUBLIC_APP_URL for cross-origin Workers hosting
This commit is contained in:
1 parent
53a0c3c825
commit
5585a6ecc3
10 files changed
+51
-25
No files matched your search
@@ -39,8 +39,8 @@ jobs:
|
||||
|
||||
# Playout
|
||||
PLAYLIST_PATH=/app/playlist/playlist.txt
|
||||
HLS_SEGMENT_DURATION=6
|
||||
HLS_WINDOW_SIZE=24
|
||||
HLS_SEGMENT_DURATION=2
|
||||
HLS_WINDOW_SIZE=12
|
||||
LOG_LEVEL=info
|
||||
|
||||
# Cloudflare R2 (required for HLS segment sync)
|
||||
|
||||
@@ -23,6 +23,13 @@ jobs:
|
||||
run: cd frontend && npm ci
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
VITE_PUBLIC_APP_URL: ${{ secrets.VITE_PUBLIC_APP_URL }}
|
||||
VITE_PUBLIC_WS_URL: ${{ secrets.VITE_PUBLIC_WS_URL }}
|
||||
VITE_PUBLIC_HLS_URL: ${{ secrets.VITE_PUBLIC_HLS_URL }}
|
||||
VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR: ${{ secrets.VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR }}
|
||||
VITE_PUBLIC_ADMIN_DEFAULT_ROOM: ${{ secrets.VITE_PUBLIC_ADMIN_DEFAULT_ROOM }}
|
||||
VITE_PUBLIC_ADMIN_MODERATION_LOG_LIMIT: "50"
|
||||
run: cd frontend && npm run build
|
||||
|
||||
- name: Deploy to Cloudflare Workers
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
> Completed tasks moved to [DONE](./DONE.md). Remaining tasks in [BACKLOG](./BACKLOG.md).
|
||||
|
||||
## Cloudflare Workers
|
||||
|
||||
- [x] Adjust `frontend/src/main.ts` to use `VITE_PUBLIC_APP_URL` for API requests instead of hardcoded `/api/...` paths.
|
||||
- [x] Adjust `frontend/src/main.ts` to use `VITE_PUBLIC_WS_URL` for WebSocket connections instead of hardcoded `wss://...` paths.
|
||||
|
||||
## Frontend Tests
|
||||
|
||||
### User Frontend
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
- **HLS segment duration 2s**: Default `HLS_SEGMENT_DURATION` changed from 6 to 2 and `HLS_WINDOW_SIZE` from 24 to 12 (2s × 12 = 24s live window), reducing end-to-end latency; the 2s GOP was already in place.
|
||||
- **Chat font sizing**: `.message-text` set to `0.95rem` (slightly smaller than the default, larger than the `0.83rem` system/flash text).
|
||||
- **R2 retention by run count + size**: Playout now keeps the newest `R2_KEEP_RUNS` run folders (default 2) and enforces an `R2_MAX_RETENTION_BYTES` cap (default 10 GiB), replacing the old 24h time-based `R2_SEGMENT_RETENTION_HOURS` cleanup. Cleanup runs after each new run plus an hourly backstop, and never deletes the live manifest. Adds `linearvoid_playout_r2_runs_retained` and `linearvoid_playout_r2_bytes_retained` gauges.
|
||||
- **Cloudflare Workers frontend hosting**: Replaced Cloudflare Pages with a Cloudflare Worker (`linearvoid-frontend`) that serves the static SPA via Workers Static Assets. Added `frontend/wrangler.toml` and renamed the deploy workflow to `.gitea/workflows/workers-deploy.yml` (builds the SPA and runs `npx wrangler deploy`). Architecture, setup/deployment, and ops documentation updated from Pages to Workers.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Login/register cross-origin API URLs**: `submitAuth` in `frontend/src/main.ts` now prefixes `/api/auth/login` and `/api/auth/register` with `VITE_PUBLIC_APP_URL` (falling back to same-origin), matching the other API calls so the Workers-served SPA reaches the app origin instead of a same-origin path.
|
||||
|
||||
### Tests
|
||||
|
||||
|
||||
@@ -262,8 +262,8 @@ See the [architecture docs](docs/architecture/README.md) for detailed architectu
|
||||
| `VITE_PUBLIC_HLS_URL` | `https://media.linearvoid.tv/hls/playlist.m3u8` | HLS playlist URL |
|
||||
| `ADMIN_USERNAME` | `admin` | Admin panel username |
|
||||
| `ADMIN_PASSWORD` | — | Admin panel password |
|
||||
| `HLS_SEGMENT_DURATION` | `6` | HLS segment duration in seconds |
|
||||
| `HLS_WINDOW_SIZE` | `24` | HLS playlist window size |
|
||||
| `HLS_SEGMENT_DURATION` | `2` | HLS segment duration in seconds |
|
||||
| `HLS_WINDOW_SIZE` | `12` | HLS playlist window size |
|
||||
|
||||
Full reference: [`.env.example`](.env.example).
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ set -e
|
||||
|
||||
echo "=== Linear Void Playout Service Starting ==="
|
||||
echo "Playlist path: ${PLAYLIST_PATH:=/app/playlist/playlist.txt}"
|
||||
echo "HLS segment duration: ${HLS_SEGMENT_DURATION:-6}s"
|
||||
echo "HLS window size: ${HLS_WINDOW_SIZE:-24}"
|
||||
echo "HLS segment duration: ${HLS_SEGMENT_DURATION:-2}s"
|
||||
echo "HLS window size: ${HLS_WINDOW_SIZE:-12}"
|
||||
|
||||
# Ensure playlist directory and file exist
|
||||
mkdir -p "$(dirname "$PLAYLIST_PATH")"
|
||||
|
||||
@@ -534,7 +534,7 @@ ffmpeg -i input.mov \
|
||||
A thread-safe, JSON-persisted runtime config store lives in `backend/chat/src/config/runtime.go` and is shared with the playout service via the playlist volume (`/app/playlist/config.json`).
|
||||
|
||||
- Editable via `GET/PUT /api/admin/config` from the admin UI.
|
||||
- Fields: `hlsSegmentDuration` (2–15s, default 6), `hlsWindowSize` (3–100, default 24), `matomoUrl`, `matomoSiteId`.
|
||||
- Fields: `hlsSegmentDuration` (2–15s, default 2), `hlsWindowSize` (3–100, default 12), `matomoUrl`, `matomoSiteId`.
|
||||
- Playout reads the same file (`loadSharedHLSConfig`) as an env fallback for HLS segment duration/window.
|
||||
- Typed setters validate values; invalid input is rejected with `400`.
|
||||
|
||||
|
||||
@@ -39,24 +39,20 @@ Serve the Vite-built SPA (`frontend/dist`) as Worker static assets:
|
||||
|
||||
See [gitea-cloudflare-workers.md](./gitea-cloudflare-workers.md) for the automated deployment workflow.
|
||||
|
||||
### Variables and secrets
|
||||
### Build-time variables
|
||||
|
||||
On the Worker, set the following environment variables (needed to run the frontend):
|
||||
The `VITE_PUBLIC_*` values are baked into the bundle at build time by Vite (`vite.config.ts` uses `envDir: ".."` to read them from the repo root). They are supplied by the Gitea Actions build environment from Gitea secrets — not as Worker runtime variables. The static-assets Worker has no runtime JavaScript, so it reads no `env` at request time.
|
||||
|
||||
| Type | Name | Value |
|
||||
| --------- | -------------------------------------- | ----------------------------------------------- |
|
||||
| Secret | ADMIN_PASSWORD | `not-a-real-admin-password` |
|
||||
| Plaintext | ADMIN_SESSION_TTL_HOURS | `12` |
|
||||
| Plaintext | ADMIN_USERNAME | `boogers` |
|
||||
| Plaintext | HLS_SEGMENT_DURATION | `2` |
|
||||
| Plaintext | HLS_WINDOW_SIZE | `12` |
|
||||
| Plaintext | PLAYLIST_PATH | `/app/playlist/playlist.txt` |
|
||||
| Plaintext | VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR | `boogers` |
|
||||
| Plaintext | VITE_PUBLIC_ADMIN_DEFAULT_ROOM | `main` |
|
||||
| Plaintext | VITE_PUBLIC_ADMIN_MODERATION_LOG_LIMIT | `50` |
|
||||
| Plaintext | VITE_PUBLIC_APP_URL | `https://linearvoid.tv` |
|
||||
| Plaintext | VITE_PUBLIC_HLS_URL | `https://media.linearvoid.tv/hls/playlist.m3u8` |
|
||||
| Plaintext | VITE_PUBLIC_WS_URL | `wss://linearvoid.tv/ws` |
|
||||
| Name | Value |
|
||||
| ---------------------------------------- | ----------------------------------------------- |
|
||||
| `VITE_PUBLIC_APP_URL` | `https://linearvoid.tv` |
|
||||
| `VITE_PUBLIC_WS_URL` | `wss://linearvoid.tv/ws` |
|
||||
| `VITE_PUBLIC_HLS_URL` | `https://media.linearvoid.tv/hls/playlist.m3u8` |
|
||||
| `VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR` | `boogers` |
|
||||
| `VITE_PUBLIC_ADMIN_DEFAULT_ROOM` | `main` |
|
||||
| `VITE_PUBLIC_ADMIN_MODERATION_LOG_LIMIT` | `50` |
|
||||
|
||||
Backend services (playout, chat, nginx) read their own runtime variables (`ADMIN_*`, `HLS_*`, `PLAYLIST_PATH`, `R2_*`, `DATABASE_URL`, `REDIS_URL`) from the container environment — see [`.env.example`](../../.env.example).
|
||||
|
||||
## Custom domains
|
||||
|
||||
|
||||
@@ -58,6 +58,13 @@ jobs:
|
||||
run: cd frontend && npm ci
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
VITE_PUBLIC_APP_URL: ${{ secrets.VITE_PUBLIC_APP_URL }}
|
||||
VITE_PUBLIC_WS_URL: ${{ secrets.VITE_PUBLIC_WS_URL }}
|
||||
VITE_PUBLIC_HLS_URL: ${{ secrets.VITE_PUBLIC_HLS_URL }}
|
||||
VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR: ${{ secrets.VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR }}
|
||||
VITE_PUBLIC_ADMIN_DEFAULT_ROOM: ${{ secrets.VITE_PUBLIC_ADMIN_DEFAULT_ROOM }}
|
||||
VITE_PUBLIC_ADMIN_MODERATION_LOG_LIMIT: "50"
|
||||
run: cd frontend && npm run build
|
||||
|
||||
- name: Deploy to Cloudflare Workers
|
||||
@@ -72,9 +79,14 @@ jobs:
|
||||
## Secrets to add in Gitea
|
||||
|
||||
| Secret | Value |
|
||||
| ----------------------- | ------------------------------------ |
|
||||
| ------------------------------------- | ------------------------------------ |
|
||||
| `CLOUDFLARE_API_TOKEN` | API token with Workers permissions |
|
||||
| `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account ID from dashboard |
|
||||
| `VITE_PUBLIC_APP_URL` | Public viewer URL |
|
||||
| `VITE_PUBLIC_WS_URL` | WebSocket endpoint |
|
||||
| `VITE_PUBLIC_HLS_URL` | HLS playlist URL |
|
||||
| `VITE_PUBLIC_ADMIN_DEFAULT_MODERATOR` | Default moderator username |
|
||||
| `VITE_PUBLIC_ADMIN_DEFAULT_ROOM` | Default chat room |
|
||||
|
||||
## Verify deployment
|
||||
|
||||
|
||||
@@ -428,7 +428,8 @@ async function submitAuth(path: string) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await fetch(path, {
|
||||
const apiUrl = import.meta.env.VITE_PUBLIC_APP_URL?.trim() || window.location.origin;
|
||||
const res = await fetch(`${apiUrl}${path}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ username: u, password: p }),
|
||||
|
||||
Reference in new issue
Block a user