A lightweight, dependency-free HTTP file server with automatic Cloudflare Quick Tunnel (cloudflared) support. Built for sharing a folder over the internet in seconds — no framework, no build step, no third-party runtime dependencies.
Developer: EFXTv
UPDOGFX2 turns the current working directory into a shareable web space:
- Browse and open files/folders
- Download a single file or an entire folder (served as a streaming zip)
- Upload files — with drag-and-drop and multi-file support
- Inline text editor for supported file types (
.txt,.py,.json,.md,.html, ...) - File / folder deletion
- Automatic public HTTPS URL via
cloudflaredQuick Tunnels when available, with graceful local fallback - Serves a project favicon and is fully usable from a phone browser
The entire implementation fits in one file and imports only Python standard library modules.
pip install updogfxRequires Python 3.8+. No other dependencies.
To use the public tunnel feature an optional cloudflared binary is needed. The server:
- Looks up
cloudflaredonPATH(shutil.which), - Falls back to
./cloudflaredin the current directory, - Exits the tunnel phase and serves locally if neither is found.
Quick setup for the binary:
updogfx -setup-setup auto-detects the OS:
- Termux → installs via
pkg install -y cloudflared - Linux → downloads the matching architecture binary from the official Cloudflare GitHub releases into the current directory (arch mapping:
x86_64→amd64,aarch64→arm64,armv7l/armv6l→arm,i686/i386→386) and sets it executable.
updogfx # cloudflared link + all features (default)
updogfx -lan # local only, bind 127.0.0.1
updogfx -share # LAN only, bind 0.0.0.0
updogfx -nodelete # disable delete
updogfx -noupload # disable upload
updogfx -p 8080 # custom port
updogfx -setup # install cloudflared for this OS
updogfx -h # help
updogfx -v # version| Flag | Effect |
|---|---|
-h, --help |
Show help |
-v, --version |
Show version |
-p, --port |
Custom port (default 3001) |
-lan |
Disables tunnel, binds 127.0.0.1 |
-share |
Disables tunnel, binds 0.0.0.0 (LAN sharing) |
-nodelete |
Disables delete operations and hides the delete buttons |
-noupload |
Disables uploads and hides the upload dropzone |
-setup |
Detects OS (Linux / Termux) and installs cloudflared |
Feature combos are independent: e.g. updogfx -nodelete -noupload yields a read-only share (a Read Only badge is shown).
http.server.ThreadingHTTPServer— per-request threads, concurrent downloads/uploads.FileHandler(SimpleHTTPRequestHandler)— all routing, rendering and file I/O live in one class.- Pure standard-library:
os,http,socketserver,subprocess,re,shutil,zipfile,mimetypes,threading,signal,urllib,html,base64,platform. - HTML is rendered from a single
HTML_TEMPLATEstring with explicitstr.format(...)injection points (no templating engine).
- GET — directory listings, raw file serving, downloads (
?download=), the inline editor (?edit=), and/favicon.ico. - POST — multipart upload (raw boundary-split parsing), delete (
action=delete) and save (action=save_edit) viaapplication/x-www-form-urlencoded. All destructive actions are POST-only; aGET ?delete=request is ignored outright. - Directory zips are built in a
tempfile.mkdtempand streamed withshutil.copyfileobj, then cleaned up on both success and failure.
start_cloudflare_tunnel()spawnscloudflared tunnel --url http://localhost:<port>withstderr=PIPEand a daemon drain thread that scans lines for thetrycloudflare.comURL — this both avoids blocking on a filled stderr pipe and surfaces the public URL without blocking.- Tunnel startup has a 30-second deadline; on timeout or process exit the server falls back to local mode.
SIGTERM/SIGINThandlers terminate the tunnel child process and exit cleanly, preventing orphanedcloudflaredprocesses on restart.
- Path traversal — every path is normalized with
os.path.abspath(os.path.join(BASE_DIR, url))and confined toBASE_DIR; traversal attempts resolve back toBASE_DIRand no-op. - XSS — all user-controlled values (breadcrumbs, filenames, editor fields, hidden inputs, hrefs) are escaped with
html.escape(..., quote=True). - MIME hardening — responses set
X-Content-Type-Options: nosniff;.html/.htm/.svgare served withContent-Disposition: attachmentto prevent stored-script execution in the same origin. - Uploads — filenames are sanitized with
os.path.basename, decoded witherrors='replace', empty/..names rejected, and uploads only land in existing directories. - Symlinks — folder zips skip symlinked files (
os.path.islink) so archives can never leak files from outsideBASE_DIR. - Dotfiles — hidden from listings by default (
HIDE_DOTFILES). - Editor — opens only for configured text extensions; writes target only if it is a regular file or does not exist.
Note: the server is intentionally unauthenticated for sharing convenience. Deletion and uploads are gated by flags; keep that in mind before exposing a public tunnel.
- Raw files are served manually (not via the parent
do_GET) so headers —Content-Type,Content-Length,Last-Modified,nosniff, attachment dispositions — are fully controlled. - Unknown paths and files requested with unrecognized query strings return a proper
404(no silent empty responses). /favicon.icoreturns a 64×64 auto-generated dog-mascot PNG embedded in the source as a base64 data URI, withCache-Control: public, max-age=86400.
updogfx/
├── __init__.py # __version__
└── main.py # full server: CLI, HTTP handler, tunnel & renderer
MIT © EFXTv
2b5af1e (updogfx 0.2.8)