Skip to content

network-plane/shareplane

Repository files navigation

shareplane - Simple HTTP Server

A lightweight HTTP server written in Go for serving files and directories over HTTP. Perfect for quick file sharing.

Features

  • Simple & Fast: Minimal overhead, easy to use
  • File & Directory Serving: Serve individual files or entire directories (URL-encoded paths, nested folders, safe rejection of .. segments)
  • HTTP Range Support: Supports HTTP Range requests (206 Partial Content) for resuming downloads and partial file fetches
  • Download Statistics: Track downloads with byte counts, per-client full/partial fetches, and optional activity/event logs
  • Customizable Binding: Configure IP address and port
  • HTTPS: Optional ephemeral self-signed certificate (--https) or PEM --cert / --key (TLS and PROXY listener are not combined; see below)
  • Network Interface Detection: When binding to 0.0.0.0, automatically shows all available IP addresses
  • File Listing: Automatic HTML file listing at the root path (search, sort, optional QR codes, multi-file archive links when enabled)
  • Glob Pattern Support: Use glob patterns to select multiple files
  • Hidden File Filtering: Hidden files (starting with .) are excluded from listings by default
  • File Hashing: Optional SHA1 hash calculation and display for files in listings
  • Customizable Colors: Customize the color scheme of the file listing interface
  • Bandwidth Limiting: Optional bandwidth throttling for file transfers
  • Rate Limiting: Built-in DoS protection with per-IP request rate limiting (default: 20 req/s)
  • Idle Timeout: Automatically shut down the server after a period of inactivity
  • Share TTL & Caps: Optional time-to-live shutdown, total byte cap, per-file max download count, IP allow/deny lists
  • HTTP Basic Auth: Optional username/password (or either alone)
  • Optional WebDAV at /webdav/ (first shared path)
  • Encrypted downloads (--encrypt): password-protected payload (AES-GCM over zstd; max 64 MiB per file; no Range)
  • One-time tokens: GET /api/one-time-token, then append ?token= to a URL (single successful GET)
  • Multi-file archives (--single-stream): GET /archive (zstd or tar.gz) and UI checkboxes
  • Uploads (--upload): POST /api/upload with multipart field files; optional subdir=; progress in the browser
  • Logging (--log): Tee server messages to a file as well as stdout
  • Stats JSON: GET /api/status; optional mirror GET /stats with --stats
  • CLI shareplane status: Print live stats from a running server (same data as /api/status)
  • Terminal --tui: Full-screen live view of /api/status (uses Bubble Tea; use --log to keep server output on disk)
  • Real-time Progress: See download progress as files are served
  • Graceful Shutdown: Print statistics on exit (SIGINT/SIGTERM)

Installation

Build from Source

go build -o shareplane

Usage

Basic Usage

Serve a single file:

./shareplane file.txt

Serve multiple files:

./shareplane file1.txt file2.txt file3.txt

Serve a directory:

./shareplane /path/to/directory

Serve multiple files and directories:

./shareplane file.txt /path/to/dir1 /path/to/dir2

Command-Line Options

  • --port: Port to listen on (default: 8080)

    ./shareplane --port 3000 file.txt
  • --url: Public base URL for generated links when behind a reverse proxy (e.g. https://share.example.com or http://192.168.1.5:8443). Used for M3U playlists and external-player stream URLs in the web UI. If omitted, the request host is used.

    ./shareplane --url https://files.example.com:8443 /path/to/share
  • --prefix / --suffix: Optional strings shown before/after each name in the HTML/API listing only (download URLs and paths are unchanged).

    ./shareplane --prefix "[" --suffix "]" /path/to/share
  • --ip: IP address to bind to (default: 0.0.0.0 - all interfaces)

    ./shareplane --ip 127.0.0.1 file.txt

    When binding to 0.0.0.0, the server will display all available network interfaces and their IP addresses.

  • --show-hidden: Show files and directories starting with a dot (.) in file listings (hidden files are hidden by default)

    ./shareplane --show-hidden /path/to/directory
  • --hash: Calculate and display SHA1 hash for files in the listing

    ./shareplane --hash /path/to/directory
  • --max-hash-size: Maximum file size (in bytes) to calculate hash for (0 = no limit, default: 0)

    ./shareplane --hash --max-hash-size 10485760 /path/to/directory  # Only hash files up to 10MB
  • --bw-limit: Bandwidth limit for file transfers (e.g., 5MB, 250KB, 5M, 1.4G, or plain bytes). No limit if not specified.

    ./shareplane --bw-limit 5MB /path/to/directory  # Limit to 5MB/s
    ./shareplane --bw-limit 1.4G /path/to/directory  # Limit to 1.4GB/s
  • --rate-limit: Rate limit: maximum requests per second per IP address (default: 20, use 0 to disable). Helps protect against DoS attacks while allowing normal browsing.

    ./shareplane --rate-limit 30 /path/to/directory    # Allow 30 requests/second per IP
    ./shareplane --rate-limit 0 /path/to/directory      # Disable rate limiting
    ./shareplane /path/to/directory                     # Uses default: 20 requests/second per IP
  • --reload: Enable auto-reload: monitor files for changes in real-time using file system notifications (new files, removed files, modified files)

    ./shareplane --reload /path/to/directory
  • --idle: Idle timeout: server shuts down after this period of inactivity. Default: 15m if flag is set without value. Supports units: M (minutes), H (hours), D (days), W (weeks), Mo (months). Examples: 15m, 1H, 4D, 1W, 1Mo

    ./shareplane --idle file.txt                    # Default: 15 minutes
    ./shareplane --idle 30m /path/to/directory     # 30 minutes
    ./shareplane --idle 2H /path/to/directory      # 2 hours
    ./shareplane --idle 1D /path/to/directory       # 1 day
    ./shareplane --idle 1W /path/to/directory       # 1 week
  • --colours: Customize the color scheme of the file listing interface. Requires 7 comma-separated colors in this order:

    1. Background (body background)
    2. Text (heading text)
    3. Table header Background
    4. Table header text
    5. Table Background
    6. Table filename text (link color)
    7. Table other text
    ./shareplane --colours "#000000,#FFFFFF,#FF0000,#FFFFFF,#CCCCCC,#0000FF,#333333" /path/to/directory

    Colors can be specified as hex codes (with or without #) or named CSS colors (e.g., red, blue, white).

  • Environment Variables:

    • PORT: Set the port (same as --port)
    • IP: Set the IP address (same as --ip)

Sharing limits and access control

  • --ttl: Stop the server after a duration from launch (plain number = minutes; or suffixes such as m, h, d, w, mo). Not persisted across restarts.
  • --byte-limit: Stop serving after this many bytes have been transferred (same units as --bw-limit).
  • --max-count: Maximum completed downloads per file (0 = unlimited).
  • --whitelist / --blacklist: Comma-separated client IPs or CIDRs (uses proxy-aware IP from X-Forwarded-For, etc.).
  • --basic-user / --basic-password: HTTP Basic authentication (either may be empty to check only the other).

HTTPS

  • --https: Listen with an ephemeral self-signed TLS certificate (not written to disk; browsers will warn).
  • --cert / --key: Paths to PEM certificate and private key. If both are set, they take precedence over --https.

When TLS is enabled, the TCP listener uses TLS directly; the HAProxy PROXY protocol wrapper is not applied on that listener.

UI and integrations

  • --qr: Show QR code buttons for direct download links in the listing.
  • --webdav: Expose WebDAV at /webdav/ (first shared path only).
  • --encrypt: Password for encrypted download bodies (see implementation limits in --help).
  • --log: Append server log output to a file as well as stdout.
  • --single-stream: Enable GET /archive (formats zstd or tar.gz) and archive checkboxes in the HTML UI.
  • --stats: Also serve GET /stats with the same JSON as /api/status (Cache-Control: no-store).
  • --tui: Run an interactive terminal dashboard polling /api/status (server runs in the background; prefer --log to capture server output).
  • --upload: Directory that receives uploaded files (POST /api/upload). Created if missing; merged into listings when not already part of the shared paths.

CLI: shareplane status

Prints live stats from a running instance (wraps GET /api/status):

shareplane status
shareplane status --url https://127.0.0.1:8443

Uses SHAREPLANE_URL when --url is omitted (default base http://127.0.0.1:8080).

Examples

Serve files on a custom port:

./shareplane --port 9000 document.pdf image.jpg

Serve only on localhost:

./shareplane --ip 127.0.0.1 --port 8080 /path/to/files

Use glob patterns:

./shareplane *.txt *.pdf

Show hidden files in listings (hidden files are hidden by default):

./shareplane --show-hidden /path/to/directory

Show SHA1 hashes for files:

./shareplane --hash /path/to/directory

Show SHA1 hashes with size limit (only hash files up to 100MB):

./shareplane --hash --max-hash-size 104857600 /path/to/directory

Limit bandwidth to 5MB/s:

./shareplane --bw-limit 5MB /path/to/directory

Customize colors with a dark theme:

./shareplane --colours "#1a1a1a,#e0e0e0,#2d2d2d,#ffffff,#252525,#4a9eff,#cccccc" /path/to/directory

Customize colors with a light blue theme:

./shareplane --colours "#f0f8ff,#1a1a1a,#4a90e2,#ffffff,#ffffff,#0066cc,#333333" /path/to/directory

Customize colors using named colors:

./shareplane --colours "black,white,red,white,gray,blue,darkgray" /path/to/directory

Access files:

  • Visit http://localhost:8080/ to see a file listing
  • Access files directly: http://localhost:8080/filename.txt

API and HTTP endpoints

Summary of useful routes (many require specific flags; see the in-app Endpoints box on the listing page):

Path Description
/ HTML file browser
/api/files JSON listing; optional ?path=
/api/search Search; q= required; optional path= scope
/api/status JSON: version, bytes, per-file and per-client stats, activity, events
/stats Same JSON as /api/status when started with --stats
/api/downloads Per-client IP and per-file full vs partial fetch counts
/api/events JSON event log
/events Server-Sent Events stream
/verify JSON SHA1 for ?file= or ?path= (relative path)
/manifest.json JSON manifest of shared items
/api/one-time-token JSON { "token": "..." } for one-time ?token= access
/archive Multi-file streaming archive when --single-stream (format=zstd or tar.gz, repeat paths=)
/api/upload POST multipart field files; optional ?subdir= when --upload is set
/webdav/ WebDAV root when --webdav

Files support query modes such as ?mode=download (default), ?mode=preview, ?mode=play, ?mode=stream (see UI). Optional ?token= consumes a one-time token from /api/one-time-token.

API details

/api/files

The primary JSON API for file listings. This is useful for scripts, tools, and automation.

Returns a JSON response with file listings, totals, and metadata.

Query Parameters:

  • path (optional): Directory path to list. If not provided, lists all shared files/directories.

Response Format:

{
  "files": [
    {
      "name": "/full/path/to/file.txt",
      "displayName": "file.txt",
      "size": 1024,
      "modTime": "2024-01-01T12:00:00Z",
      "hash": "abc123...",
      "isDir": false
    }
  ],
  "totalSize": 1048576,
  "fileCount": 10,
  "showHash": true
}

Response Fields:

  • files: Array of file/directory objects
    • name: Full absolute path (internal use)
    • displayName: Relative path for display
    • size: File size in bytes
    • modTime: Modification time (ISO 8601 format)
    • hash: SHA1 hash (empty if not calculated or disabled)
    • isDir: Boolean indicating if this is a directory
  • totalSize: Total size of all files in bytes (directories excluded)
  • fileCount: Total number of files (directories excluded)
  • showHash: Boolean indicating if hash calculation is enabled

API Usage Examples

List all shared files (root):

curl http://localhost:8080/api/files

List files in a specific directory:

curl "http://localhost:8080/api/files?path=subdirectory"

Pretty-print JSON response:

curl http://localhost:8080/api/files | jq

List files and extract only file names:

curl -s http://localhost:8080/api/files | jq -r '.files[] | select(.isDir == false) | .displayName'

Get total size of all files:

curl -s http://localhost:8080/api/files | jq '.totalSize'

List files with their sizes (formatted):

curl -s http://localhost:8080/api/files | jq -r '.files[] | "\(.displayName): \(.size) bytes"'

Download a file using curl:

curl -O http://localhost:8080/filename.txt

Download with progress bar:

curl -# -O http://localhost:8080/largefile.zip

Resume a partial download:

curl -C - -O http://localhost:8080/largefile.zip

Check if a file exists (HEAD request):

curl -I http://localhost:8080/filename.txt

Get file metadata without downloading:

curl -I http://localhost:8080/filename.txt

List files in a nested directory:

curl "http://localhost:8080/api/files?path=docs/subdir"

Filter directories only:

curl -s http://localhost:8080/api/files | jq '.files[] | select(.isDir == true) | .displayName'

Get files with hashes (when --hash is enabled):

curl -s http://localhost:8080/api/files | jq '.files[] | select(.hash != "") | {name: .displayName, hash: .hash}'

Save API response to file:

curl -s http://localhost:8080/api/files -o file_listing.json

Use API in a script (bash example):

#!/bin/bash
API_URL="http://localhost:8080/api/files"
FILES=$(curl -s "$API_URL" | jq -r '.files[] | select(.isDir == false) | .displayName')

for file in $FILES; do
    echo "Processing: $file"
    # Your processing logic here
done

curl examples (download and API)

Replace HOST with your server (e.g. http://127.0.0.1:8080 or your public URL).

Download a file (save with remote filename):

curl -OJ "HOST/path/to/file.ext"

Download to a specific local path:

curl -o "local-name.ext" "HOST/path/to/file.ext"

Resume / partial download (Range is supported):

curl -C - -o "file.ext" "HOST/path/to/file.ext"

Probe with HEAD (no body):

curl -I "HOST/path/to/file.ext"

JSON file listing:

curl -s "HOST/api/files" | jq .
curl -s "HOST/api/files?path=relative/subdir" | jq .

Search under a folder:

curl -s "HOST/api/search?q=part" | jq .
curl -s "HOST/api/search?q=part&path=relative/subdir" | jq .

SHA1 for a file (path is relative to the share roots):

curl -s "HOST/verify?file=relative/path/file.ext" | jq .

Upload (requires --upload DIR):

curl -s -F "files=@./local.txt" "HOST/api/upload"
# Optional subfolder under the upload root (must stay inside it):
curl -s -F "files=@./local.txt" "HOST/api/upload?subdir=incoming"

The HTML listing shows an upload control with progress when --upload is set.

When binding to 0.0.0.0, the server will show output like:

Serving on http://0.0.0.0:8080
Available on:
  http://192.168.1.100:8080
  http://10.0.0.5:8080
  http://127.0.0.1:8080
  http://localhost:8080

HTTP Range Requests

The server fully supports HTTP Range requests (RFC 7233), which enables:

  • Resuming Downloads: Clients can resume interrupted downloads by requesting specific byte ranges
  • Partial Fetches: Clients can request specific portions of files (e.g., for video streaming or large file processing)
  • Efficient Transfers: Reduces bandwidth usage when only part of a file is needed

The server automatically handles Range headers and responds with 206 Partial Content when appropriate. This is transparent to users - any HTTP client that supports Range requests will automatically benefit from this feature.

Proxy Support

When running behind a reverse proxy (such as frps, nginx, or Cloudflare), the server automatically detects and uses the real client IP address from proxy headers. The server checks the following headers in order:

  1. X-Forwarded-For - Most common header, contains the original client IP
  2. X-Real-IP - Common in nginx and other proxies
  3. X-Forwarded - Alternative format for forwarded IPs
  4. CF-Connecting-IP - Cloudflare-specific header

If no proxy headers are present, the server falls back to the connection's RemoteAddr. The real client IP is displayed in the download logs, making it easy to track which clients are downloading files even when behind a proxy.

Statistics

The server tracks download statistics for each file:

  • Number of times each file was downloaded
  • Total bytes sent for each file
  • Total bytes sent for file listings
  • Per-client full vs partial fetches (see /api/downloads and /api/status)

Use shareplane status or GET /api/status (and optional GET /stats with --stats) for live aggregates while the server is running.

Statistics are also printed when the server is terminated (Ctrl+C or SIGTERM), and when using --tui after you quit the TUI.

License

See LICENSE file for details.

About

No description or website provided.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages