crosspoint-reader/docs/webserver-api-reference.md
2026-01-25 21:22:49 -05:00

8.2 KiB

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

{
  "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
[
  {"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

[
  {"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
{"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

WebSocket Protocol (port 81)

Handler: onWebSocketEvent() via wsEventCallback() trampoline

Upload Protocol

  1. Client connects
  2. Server: (implicit connection acknowledgment)
  3. Client TEXT: START:<filename>:<size>:<path>
  4. Server TEXT: READY or ERROR:<message>
  5. Client BIN: file data chunks (any size, recommend 64KB)
  6. Server TEXT: PROGRESS:<received>:<total> (every 64KB or at end)
  7. Server TEXT: DONE or ERROR:<message>

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

  • <WebServer.h> - ESP32 HTTP server
  • <WebSocketsServer.h> - WebSocket support
  • <ArduinoJson.h> - JSON serialization
  • <SDCardManager.h> - SD card operations (SdMan singleton)
  • <Epub.h> - Epub cache management
  • BookManager.h - Book deletion, archiving, recent books
  • StringUtils.h - File extension checking