|
| 1 | +# Migration from iframe to Fetch API# Migration to Fetch API |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +## Overview## Summary |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +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. |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +## Changes Made## Changes Made |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +### 1. Frontend (JavaScript)### Backend (main.go) |
| 18 | + |
| 19 | + |
| 20 | + |
| 21 | +#### Removed Components1. **Added APIResponse struct** - Standard JSON response structure |
| 22 | + |
| 23 | +- **Hidden iframe and form** (`index.html`): Removed the `<iframe>` and `<form>` elements that were used for API communication ```go |
| 24 | + |
| 25 | +- **`loadFromServer()` function**: Replaced with modern `fetchAPI()` function type APIResponse struct { |
| 26 | + |
| 27 | +- **`checkDataframe()` function**: Removed the timeout monitoring mechanism (no longer needed with fetch) Status string `json:"status"` |
| 28 | + |
| 29 | +- **`dataframeTime` variable**: Removed global timeout tracking variable Data interface{} `json:"data,omitempty"` |
| 30 | + |
| 31 | + Error string `json:"error,omitempty"` |
| 32 | + |
| 33 | +#### Added Components } |
| 34 | + |
| 35 | +- **`fetchAPI()` function**: New async function using modern Fetch API ``` |
| 36 | + |
| 37 | + - Automatically handles JSON request/response |
| 38 | + |
| 39 | + - Built-in error handling with try/catch2. **Updated handleRequest** - Now accepts JSON requests instead of form data |
| 40 | + |
| 41 | + - Cleaner async/await syntax - Changed from `c.PostForm("dffunc")` to JSON body parsing |
| 42 | + |
| 43 | + - No more timeout polling - relies on browser's native timeout handling - Request format: `{"function": "...", "data": "..."}` |
| 44 | + |
| 45 | + |
| 46 | + |
| 47 | +#### Updated Functions3. **Updated all API handlers** - Return proper JSON instead of HTML with embedded JavaScript |
| 48 | + |
| 49 | +All functions that previously called `loadFromServer()` now use `fetchAPI()`: - `handleVersion` → Returns `{status: "ok", data: "version"}` |
| 50 | + # Migration: iframe → Fetch API |
| 51 | + |
| 52 | + ## Summary |
| 53 | + |
| 54 | + 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). |
| 55 | + |
| 56 | + ## Goals |
| 57 | + |
| 58 | + - Replace iframe/form callbacks with Fetch-based API calls. |
| 59 | + - Standardize request/response shapes as JSON objects. |
| 60 | + - Keep backward compatibility during the migration where practical. |
| 61 | + - Remove dead helpers that were specific to the iframe approach. |
| 62 | + |
| 63 | + ## What changed (high level) |
| 64 | + |
| 65 | + - Frontend now uses an async `fetchAPI(functionName, data)` wrapper to call `/api`. |
| 66 | + - Backend `handleRequest` accepts JSON bodies and still falls back to form parsing for legacy compatibility. |
| 67 | + - All handlers return JSON objects instead of HTML pages that contain JavaScript callbacks. |
| 68 | + - Hidden iframe, form inputs, and related helper plumbing were removed from the frontend. |
| 69 | + - A few small compatibility helpers were removed from the codebase (see "Removed functions" below). |
| 70 | + |
| 71 | + ## Key differences (request/response shapes) |
| 72 | + |
| 73 | + - Old (iframe): responses were returned in HTML with embedded JavaScript and callback invocation like parent.cb([...]) or used custom array formats. |
| 74 | + - New (fetch): responses are JSON objects, e.g. `{ "status": "ok", "files": [...] }` or `{ "status": "ok", "dir": "...", "dirs": [...], "files": [...] }`. |
| 75 | + |
| 76 | + Frontend code now expects and handles these JSON objects directly. |
| 77 | + |
| 78 | + ## Removed / cleaned up |
| 79 | + |
| 80 | + These helpers were specific to the iframe callback approach and were removed to reduce dead code: |
| 81 | + |
| 82 | + - `echoReqHtml()` — HTML wrapper used to execute parent callbacks from an iframe. |
| 83 | + - `ea()` — JS helper that encoded arrays into a string for embedding in HTML callback arguments. |
| 84 | + - `setVersion()` (frontend) — compatibility wrapper; version rendering is handled directly by `loadVersion()` now. |
| 85 | + |
| 86 | + In Go code, leftover helpers used only for the iframe flow were also removed. |
| 87 | + |
| 88 | + ## Notable updated handlers (backend) |
| 89 | + |
| 90 | + - `handleRequest` — accepts JSON (`Content-Type: application/json`) and falls back to form parsing if needed. It dispatches on the request `function` field and returns JSON. |
| 91 | + - `handleVersion` — returns `{status: "ok", "version": "..."}`. |
| 92 | + - `handleDirRequest`, `handleGetAllMp3`, `handleGetAllMp3InDir`, `handleGetAllDirs`, `handleGetAllMp3InDirs`, `handleSearchTitle`, `handleSearchDir` — all return consistent JSON shapes. |
| 93 | + |
| 94 | + The backend changes are focused on returning proper JSON and preserving behaviors (directory listing, searches, presigned URLs for S3, or local-file routing). |
| 95 | + |
| 96 | + ## Frontend changes (static/script.js) |
| 97 | + |
| 98 | + - New `fetchAPI()` async wrapper that sends JSON and parses JSON responses. |
| 99 | + - `loadVersion()` is async and updates the version DOM element directly. |
| 100 | + - UI callbacks (`getBrowserData`, `getSearchTitle`, `getSearchDir`, etc.) now accept JSON objects and handle them without iframe callbacks. |
| 101 | + |
| 102 | + ## Backward compatibility |
| 103 | + |
| 104 | + - During migration, the backend still accepts form-encoded requests (legacy) so you can deploy the backend before the frontend. |
| 105 | + - After migration stabilizes, the fallback form parsing can be removed for simplification. |
| 106 | + |
| 107 | + ## Benefits |
| 108 | + |
| 109 | + - Simpler and clearer code (no HTML generation for data transport). |
| 110 | + - Easier debugging in browser DevTools (JSON is visible in Network tab). |
| 111 | + - Better reliability when deploying to serverless platforms (Lambda + API Gateway). |
| 112 | + - Cleaner API contract between frontend and backend. |
| 113 | + |
| 114 | + ## Testing checklist |
| 115 | + |
| 116 | + Run these locally before/after deployment: |
| 117 | + |
| 118 | + - [x] Directory browsing (browse directories and see file lists) |
| 119 | + - [x] Version loads and displays in the UI |
| 120 | + - [x] Search by title (results show expected matches) |
| 121 | + - [x] Search by directory (results show expected matches) |
| 122 | + - [x] Get all MP3(s) and per-directory MP3 listings |
| 123 | + - [x] Audio playback (play, pause, next/prev, progress) |
| 124 | + |
| 125 | + Local test commands that are useful: |
| 126 | + |
| 127 | + ```bash |
| 128 | + # build |
| 129 | + go build -v -ldflags="-w -s -X 'main.Version=dev'" -o go-music . |
| 130 | + # run |
| 131 | + MUSIC_DIR=./mp3 ./go-music |
| 132 | + # open |
| 133 | + http://localhost:8080 |
| 134 | + ``` |
| 135 | + |
| 136 | + - Run unit tests (uses MUSIC_DIR to avoid S3 init): |
| 137 | + |
| 138 | + ```bash |
| 139 | + MUSIC_DIR=/tmp/gotest go test -v |
| 140 | + ``` |
| 141 | + |
| 142 | + ## Rollback plan |
| 143 | + |
| 144 | + If issues are discovered, you can revert to a commit before the migration and redeploy. All previous iframe-based code remains available in git history. |
| 145 | + |
| 146 | + ## Code cleanup opportunities (post-migration) |
| 147 | + |
| 148 | + Once the new fetch-based flow is stable, consider removing: |
| 149 | + |
| 150 | + 1. Form-data fallback parsing in `handleRequest()`. |
| 151 | + 2. Any leftover iframe/form DOM elements in `static/index.html`. |
| 152 | + 3. Any migration-only comments or shim helpers in the codebase. |
| 153 | + |
| 154 | + ## Notes about `setVersion()` |
| 155 | + |
| 156 | + `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. |
| 157 | + |
| 158 | + ## Next steps |
| 159 | + |
| 160 | + - Verify the application behavior in a staging environment (Lambda or local) and run the testing checklist above. |
| 161 | + - If everything is stable for a few deploy cycles, remove legacy fallbacks and migration notes. |
| 162 | + - 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. |
| 163 | + |
| 164 | + ## Conclusion |
| 165 | + |
| 166 | + 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. |
0 commit comments