This document describes the migration from the legacy iframe-based API communication to the modern Fetch API approach.Successfully migrated the go-music application from the old-fashioned iframe-based API communication pattern to modern Fetch API.
-
Hidden iframe and form (
index.html): Removed the<iframe>and<form>elements that were used for API communication ```go -
loadFromServer()function: Replaced with modernfetchAPI()function type APIResponse struct { -
checkDataframe()function: Removed the timeout monitoring mechanism (no longer needed with fetch) Status stringjson:"status" -
dataframeTimevariable: Removed global timeout tracking variable Data interface{}json:"data,omitempty"Error string `json:"error,omitempty"`
-
fetchAPI()function: New async function using modern Fetch API ```-
Automatically handles JSON request/response
-
Built-in error handling with try/catch2. Updated handleRequest - Now accepts JSON requests instead of form data
-
Cleaner async/await syntax - Changed from
c.PostForm("dffunc")to JSON body parsing -
No more timeout polling - relies on browser's native timeout handling - Request format:
{"function": "...", "data": "..."}
-
Updated Functions3. Updated all API handlers - Return proper JSON instead of HTML with embedded JavaScript
All functions that previously called loadFromServer() now use fetchAPI(): - handleVersion → Returns {status: "ok", data: "version"}
This document summarizes the migration from the legacy iframe/form-based frontend API integration to a modern Fetch API approach. The change simplifies client-server communication by using standard JSON requests and responses, removes fragile iframe callbacks, and improves maintainability and reliability (particularly for Lambda deployments).
- Replace iframe/form callbacks with Fetch-based API calls.
- Standardize request/response shapes as JSON objects.
- Keep backward compatibility during the migration where practical.
- Remove dead helpers that were specific to the iframe approach.
- Frontend now uses an async
fetchAPI(functionName, data)wrapper to call/api. - Backend
handleRequestaccepts JSON bodies and still falls back to form parsing for legacy compatibility. - All handlers return JSON objects instead of HTML pages that contain JavaScript callbacks.
- Hidden iframe, form inputs, and related helper plumbing were removed from the frontend.
- A few small compatibility helpers were removed from the codebase (see "Removed functions" below).
- Old (iframe): responses were returned in HTML with embedded JavaScript and callback invocation like parent.cb([...]) or used custom array formats.
- New (fetch): responses are JSON objects, e.g.
{ "status": "ok", "files": [...] }or{ "status": "ok", "dir": "...", "dirs": [...], "files": [...] }.
Frontend code now expects and handles these JSON objects directly.
These helpers were specific to the iframe callback approach and were removed to reduce dead code:
echoReqHtml()— HTML wrapper used to execute parent callbacks from an iframe.ea()— JS helper that encoded arrays into a string for embedding in HTML callback arguments.
In Go code, leftover helpers used only for the iframe flow were also removed.
handleRequest— accepts JSON (Content-Type: application/json) and falls back to form parsing if needed. It dispatches on the requestfunctionfield and returns JSON.handleDirRequest,handleGetAllMp3,handleGetAllMp3InDir,handleGetAllDirs,handleGetAllMp3InDirs,handleSearchTitle,handleSearchDir— all return consistent JSON shapes.
The backend changes are focused on returning proper JSON and preserving behaviors (directory listing, searches, presigned URLs for S3, or local-file routing).
- New
fetchAPI()async wrapper that sends JSON and parses JSON responses. - UI callbacks (
getBrowserData,getSearchTitle,getSearchDir, etc.) now accept JSON objects and handle them without iframe callbacks.
- During migration, the backend still accepts form-encoded requests (legacy) so you can deploy the backend before the frontend.
- After migration stabilizes, the fallback form parsing can be removed for simplification.
- Simpler and clearer code (no HTML generation for data transport).
- Easier debugging in browser DevTools (JSON is visible in Network tab).
- Better reliability when deploying to serverless platforms (Lambda + API Gateway).
- Cleaner API contract between frontend and backend.
Run these locally before/after deployment:
- Directory browsing (browse directories and see file lists)
- Search by title (results show expected matches)
- Search by directory (results show expected matches)
- Get all MP3(s) and per-directory MP3 listings
- Audio playback (play, pause, next/prev, progress)
Local test commands that are useful:
# build
go build -v -ldflags="-w -s -X 'main.Version=dev'" -o go-music .
# run
MUSIC_DIR=./mp3 ./go-music
# open
http://localhost:8080- Run unit tests (uses MUSIC_DIR to avoid S3 init):
MUSIC_DIR=/tmp/gotest go test -vIf issues are discovered, you can revert to a commit before the migration and redeploy. All previous iframe-based code remains available in git history.
Once the new fetch-based flow is stable, consider removing:
- Form-data fallback parsing in
handleRequest(). - Any leftover iframe/form DOM elements in
templates/index.html. - Any migration-only comments or shim helpers in the codebase.
setVersion() (a small frontend compatibility helper used in the iframe approach) was removed from static/script.js. The async loadVersion() function now updates the UI directly. MIGRATION.md and other docs were updated to note this removal.
- Verify the application behavior in a staging environment (Lambda or local) and run the testing checklist above.
- If everything is stable for a few deploy cycles, remove legacy fallbacks and migration notes.
- Consider adding a small section in the README summarizing how the API expects to be called (JSON
{function, data}) so future contributors understand the contract.
This migration modernizes the frontend-backend contract and removes brittle iframe callback plumbing. It improves maintainability, observability, and serverless compatibility while keeping the user-facing behavior unchanged.