# CrossPointWebServer API Reference Source: `src/network/CrossPointWebServer.cpp` and `CrossPointWebServer.h` ## Server Configuration - HTTP port: 80 (default) - WebSocket port: 81 (default) - WiFi sleep disabled for responsiveness - Supports both STA (station) and AP (access point) modes ## HTTP Endpoints ### GET / **Handler:** `handleRoot()` **Response:** HTML homepage from `HomePageHtml` (generated from `html/HomePage.html`) **Content-Type:** text/html ### GET /files **Handler:** `handleFileList()` **Response:** HTML file browser page from `FilesPageHtml` (generated from `html/FilesPage.html`) **Content-Type:** text/html ### GET /api/status **Handler:** `handleStatus()` **Response:** JSON device status **Content-Type:** application/json ```json { "version": "CROSSPOINT_VERSION", "ip": "192.168.x.x", "mode": "AP" | "STA", "rssi": -50, // 0 in AP mode "freeHeap": 123456, "uptime": 3600 // seconds } ``` ### GET /api/files **Handler:** `handleFileListData()` **Query params:** - `path` (optional): Directory path, defaults to "/" - `showHidden` (optional): "true" to show dot-files (except .crosspoint) **Response:** JSON array of files **Content-Type:** application/json ```json [ {"name": "book.epub", "size": 123456, "isDirectory": false, "isEpub": true}, {"name": "folder", "size": 0, "isDirectory": true, "isEpub": false} ] ``` **Notes:** - Hidden by default: files starting with ".", "System Volume Information", "XTCache" - Always hidden: ".crosspoint" (internal cache folder) - Streamed response (chunked encoding) to reduce memory usage ### GET /api/archived **Handler:** `handleArchivedList()` **Response:** JSON array of archived books **Content-Type:** application/json ```json [ {"filename": "archived_file.epub", "originalPath": "/Books/archived_file.epub"} ] ``` **Notes:** Uses `BookManager::listArchivedBooks()` and `BookManager::getArchivedBookOriginalPath()` ### GET /download **Handler:** `handleDownload()` **Query params:** - `path` (required): File path to download **Response:** File binary with Content-Disposition attachment header **Content-Type:** application/octet-stream **Errors:** - 400: Missing path, path is directory - 403: Hidden/system file, protected item - 404: File not found **Notes:** - Streams in 4KB chunks - Updates `totalBytesDownloaded` and `totalFilesDownloaded` stats - Security: rejects paths with "..", files starting with ".", protected items ### POST /upload **Handler:** `handleUpload()` (multipart handler), `handleUploadPost()` (response handler) **Query params:** - `path` (optional): Upload directory, defaults to "/" **Form data:** multipart/form-data with file **Response:** "File uploaded successfully: filename" or error message **Notes:** - Uses 4KB write buffer for SD card efficiency - Overwrites existing files - Clears epub cache after upload via `clearEpubCacheIfNeeded()` - Updates `totalBytesUploaded` and `totalFilesUploaded` stats - Logs progress every 100KB ### POST /mkdir **Handler:** `handleCreateFolder()` **Form params:** - `name` (required): Folder name - `path` (optional): Parent directory, defaults to "/" **Response:** "Folder created: foldername" or error **Errors:** - 400: Missing name, empty name, folder exists ### POST /delete **Handler:** `handleDelete()` **Form params:** - `path` (required): Item path to delete - `type` (optional): "file" (default) or "folder" - `archived` (optional): "true" for archived books **Response:** "Deleted successfully" or error **Errors:** - 400: Missing path, root directory, folder not empty - 403: Hidden/system file, protected item - 404: Item not found - 500: Delete failed **Notes:** - For files: uses `BookManager::deleteBook()` which handles cache and recent books cleanup - For folders: must be empty first - For archived: passes filename to `BookManager::deleteBook(filename, true)` ### POST /archive **Handler:** `handleArchive()` **Form params:** - `path` (required): Book path to archive **Response:** "Book archived successfully" or error **Notes:** Uses `BookManager::archiveBook()` ### POST /unarchive **Handler:** `handleUnarchive()` **Form params:** - `filename` (required): Archived book filename **Response:** JSON with original path **Content-Type:** application/json ```json {"success": true, "originalPath": "/Books/book.epub"} ``` **Notes:** Uses `BookManager::unarchiveBook()` and `BookManager::getArchivedBookOriginalPath()` ### POST /rename **Handler:** `handleRename()` **Form params:** - `path` (required): Current item path - `newName` (required): New name (filename only, no path separators) **Response:** "Renamed successfully" or error **Errors:** - 400: Missing params, empty name, name contains "/" or "\\", root directory, destination exists - 403: System file, protected item - 404: Source not found - 500: Rename failed **Notes:** - Renames in place (same directory, new name) - Uses `SdMan.rename()` - Clears epub cache after rename via `clearEpubCacheIfNeeded()` ### POST /copy **Handler:** `handleCopy()` **Form params:** - `srcPath` (required): Source path - `destPath` (required): Full destination path (including new name) **Response:** "Copied successfully" or error **Errors:** - 400: Missing params, root directory, destination exists, copy into self - 403: System file, protected item - 404: Source not found - 500: Copy failed **Notes:** - Uses `copyFile()` for files (4KB buffer chunks) - Uses `copyFolder()` for recursive directory copy - Skips hidden files in folder copy ### POST /move **Handler:** `handleMove()` **Form params:** - `srcPath` (required): Source path - `destPath` (required): Full destination path (including new name) **Response:** "Moved successfully" or error **Errors:** Same as copy **Notes:** - First attempts atomic `SdMan.rename()` (fast) - Falls back to copy+delete if rename fails - Uses `deleteFolderRecursive()` for folder cleanup ### GET /list **Handler:** `handleListGet()` **Query params:** - `name` (optional): Specific list name to retrieve **Response:** JSON array of lists (if no name) or single list details (if name specified) **Content-Type:** application/json **Response (all lists - no name param):** ```json [ {"name": "MyReadingList", "path": "/.lists/MyReadingList.bin", "bookCount": 5}, {"name": "Favorites", "path": "/.lists/Favorites.bin", "bookCount": 12} ] ``` **Response (specific list - with name param):** ```json { "name": "MyReadingList", "path": "/.lists/MyReadingList.bin", "books": [ {"order": 1, "title": "The Great Gatsby", "author": "F. Scott Fitzgerald", "path": "/Books/gatsby.epub"}, {"order": 2, "title": "1984", "author": "George Orwell", "path": "/Books/1984.epub"} ] } ``` **Errors:** - 404: List not found (when `name` specified but doesn't exist) **Notes:** - Lists are stored in `/.lists/` directory as `.bin` files - Uses `BookListStore::listAllLists()` and `BookListStore::loadList()` ### POST /list **Handler:** `handleListPost()` **Query params:** - `action` (required): "upload" or "delete" - `name` (required): List name (without .bin extension) **Request body (for upload):** CSV text with one book per line **Content-Type:** text/plain (for upload body) **Input format (POST body for upload action):** ``` 1,The Great Gatsby,F. Scott Fitzgerald,/Books/gatsby.epub 2,1984,George Orwell,/Books/1984.epub 3,Pride and Prejudice,Jane Austen,/Books/pride.epub ``` Format: `order,title,author,path` (one per line) **Response (upload success):** ```json {"success": true, "path": "/.lists/MyReadingList.bin"} ``` **Response (delete success):** ```json {"success": true} ``` **Errors:** - 400: Missing action or name parameter, empty name, failed to parse list data - 404: List not found (for delete action) - 500: Failed to save/delete list **Notes:** - Lists are stored as binary files in `/.lists/` directory - Uses `BookListStore::parseFromText()`, `BookListStore::saveList()`, `BookListStore::deleteList()` - Order field determines display order (books are sorted by order when loaded) - Overwrites existing list with same name on upload ## WebSocket Protocol (port 81) **Handler:** `onWebSocketEvent()` via `wsEventCallback()` trampoline ### Upload Protocol 1. Client connects 2. Server: (implicit connection acknowledgment) 3. Client TEXT: `START:::` 4. Server TEXT: `READY` or `ERROR:` 5. Client BIN: file data chunks (any size, recommend 64KB) 6. Server TEXT: `PROGRESS::` (every 64KB or at end) 7. Server TEXT: `DONE` or `ERROR:` ### Events - `WStype_CONNECTED`: Client connected, logs connection - `WStype_DISCONNECTED`: Cleanup incomplete upload, delete partial file - `WStype_TEXT`: Parse control messages (START) - `WStype_BIN`: Write file data, send progress, complete upload ### Notes - Faster than HTTP multipart for large files - Direct binary writes to SD card - Clears epub cache after upload - Updates traffic statistics ## Security ### Protected Items (HIDDEN_ITEMS[]) - "System Volume Information" - "XTCache" ### Always Hidden - ".crosspoint" (internal cache) ### Security Checks Applied To - `/delete`: Rejects dot-files (unless archived), protected items - `/download`: Rejects dot-files, protected items, path traversal (..) - `/rename`: Rejects dot-files, protected items - `/copy`: Rejects dot-files, protected items - `/move`: Rejects dot-files, protected items ## Helper Functions ### clearEpubCacheIfNeeded(filePath) - Location: anonymous namespace at top of file - Clears epub cache if file ends with ".epub" - Uses `Epub(filePath, "/.crosspoint").clearCache()` - Called by: upload, WebSocket upload, rename ### scanFiles(path, callback, showHidden) - Iterates directory, calls callback for each FileInfo - Yields and resets watchdog during iteration - Filters hidden items based on showHidden flag ### copyFile(srcPath, destPath) / copyFolder(srcPath, destPath) - 4KB buffer for file copy - Recursive for folders - Returns bool success ### deleteFolderRecursive(path) - Static helper for move fallback - Recursively deletes contents then directory ## Traffic Statistics (mutable, updated from const handlers) - `totalBytesUploaded` - `totalBytesDownloaded` - `totalFilesUploaded` - `totalFilesDownloaded` - `serverStartTime` (for uptime calculation) ## Dependencies - `` - ESP32 HTTP server - `` - WebSocket support - `` - JSON serialization - `` - SD card operations (SdMan singleton) - `` - Epub cache management - `BookListStore.h` - Book list management (lists feature) - `BookManager.h` - Book deletion, archiving, recent books - `StringUtils.h` - File extension checking