Skip to content

Instantly share code, notes, and snippets.

@hrbrmstr
Created November 29, 2022 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hrbrmstr/eb60d7d1f79704c8c4151961458d5c94 to your computer and use it in GitHub Desktop.
Save hrbrmstr/eb60d7d1f79704c8c4151961458d5c94 to your computer and use it in GitHub Desktop.

Drop #145 (2022-11-29): HTTP RIGHT NOW!

http.server (🐍); http-server (JS); devd (golang); miniserve (Rust)

Whether exfiltrating company seekrits, letting a friend quickly grab some movie you torrented, or legitimately needing to test some HTML/JS/WASM/CSS creation you've built, sometimes you just need to fire up a web server right now with as little pain as possible. Depending on your preferred base environment, you may be able to "live off the land" and not even have to install anything; or, you may want to BYO cross-platform single-executable wherever you find yourself. Regardless of the environment, there are some considerations to take into account:

  • Do you need TLS enabled?
  • Is CGI functionality necessary?
  • Would having an automagically available domain name to use be helpful?
  • How fancy do you need the default directory viewer
  • Will your use-case benefit from being able to monitor files for changes?
  • Might CORS support be helpful?
  • Should it support file uploads and/or authentication?

Rather than expound on each of these today, I'm dropping repo links and the "help" output for each, and will leave expository about my #1 and #2 choices for future editions. There will, ofc, be some obligatory pot shots at the truly inferior members of the list.

Let's begin…

http.server (🐍)

With the final coming of age of an almost usable-by-default Python installation (i.e., later Python 3.x versions), gone are the days of the "venerable" -m SimpleHTTPServer command line parameters which would have made the current, or specified, directory available locally or to the local LAN or scary internets. Now, said incantation is an easier to type -m http.server with the barest of bones for options:

usage: server.py [-h] [--cgi] [--bind ADDRESS] [--directory DIRECTORY] [port]

positional arguments:
  port                  specify alternate port (default: 8000)

options:
  -h, --help            show this help message and exit
  --cgi                 run as CGI server
  --bind ADDRESS, -b ADDRESS
                        specify alternate bind address (default: all interfaces)
  --directory DIRECTORY, -d DIRECTORY
                        specify alternate directory (default: current directory)

Python is, sadly, likely taking up precious storage space on any given system you may find yourself using, making this the most ubiquitously supported way to get your web on.

http-server (JS)

If JavaScript is more up your alley, you likely already know about http-server

A quick npm install -g http-server gives you loads of options to choose from:

usage: http-server [path] [options]

options:
  -p --port    Port to use. If 0, look for open port. [8080]
  -a           Address to use [0.0.0.0]
  -d           Show directory listings [true]
  -i           Display autoIndex [true]
  -g --gzip    Serve gzip files when possible [false]
  -b --brotli  Serve brotli files when possible [false]
               If both brotli and gzip are enabled, brotli takes precedence
  -e --ext     Default file extension if none supplied [none]
  -s --silent  Suppress log messages from output
  --cors[=headers]   Enable CORS via the "Access-Control-Allow-Origin" header
                     Optionally provide CORS headers list separated by commas
  -o [path]    Open browser window after starting the server.
               Optionally provide a URL path to open the browser window to.
  -c           Cache time (max-age) in seconds [3600], e.g. -c10 for 10 seconds.
               To disable caching, use -c-1.
  -t           Connections timeout in seconds [120], e.g. -t60 for 1 minute.
               To disable timeout, use -t0
  -U --utc     Use UTC time format in log messages.
  --log-ip     Enable logging of the client's IP address

  -P --proxy       Fallback proxy if the request cannot be resolved. e.g.: http://someurl.com
  --proxy-options  Pass options to proxy using nested dotted objects. e.g.: --proxy-options.secure false

  --username   Username for basic authentication [none]
               Can also be specified with the env variable NODE_HTTP_SERVER_USERNAME
  --password   Password for basic authentication [none]
               Can also be specified with the env variable NODE_HTTP_SERVER_PASSWORD

  -S --tls --ssl   Enable secure request serving with TLS/SSL (HTTPS)
  -C --cert    Path to TLS cert file (default: cert.pem)
  -K --key     Path to TLS key file (default: key.pem)

  -r --robots        Respond to /robots.txt [User-agent: *\nDisallow: /]
  --no-dotfiles      Do not show dotfiles
  --mimetypes        Path to a .types file for custom mimetype definition
  -h --help          Print this list and exit.
  -v --version       Print the version and exit.

making this one of the most flexible options, provided you don't mind bringing a few dependencies along for the ride:

devd (golang)

If both portability and high functionality are in your "must have" list, then, perhaps, look no further than the treasured golang utility, devd.

This utility seem to grok the needs of both developers and "hackers":

usage: devd [<flags>] <route>...

Flags:
  -h, --help                 Show context-sensitive help (also try --help-long and --help-man).
  -A, --address="127.0.0.1"  Address to listen on
  -a, --all                  Listen on all addresses
  -c, --cert=PATH            Certificate bundle file - enables TLS
  -C, --color                Enable colour output, even if devd is not connected to a terminal
  -d, --down=N               Throttle downstream from the client to N kilobytes per second
  -f, --notfound=PATH ...    Default when a static file is not found
  -H, --logheaders           Log headers
  -I, --ignore=REGEX ...     Disable logging matching requests. Regexes are matched over 'host/path'
  -L, --livereload           Enable livereload
  -l, --livewatch            Enable livereload and watch for static file changes
  -m, --modd                 Modd is our parent - synonym for -LCt
  -n, --latency=N            Add N milliseconds of round-trip latency
  -o, --open                 Open browser window on startup
  -p, --port=PORT            Port to listen on - if not specified, devd will auto-pick a sensible port
  -P, --password=USER:PASS   HTTP basic password protection
  -q, --quiet                Silence all logs
  -s, --tls                  Serve TLS with auto-generated self-signed certificate (~/.devd.cert)
  -t, --notimestamps         Disable timestamps in output
  -T, --logtime              Log timing
  -u, --up=N                 Throttle upstream from the client to N kilobytes per second
  -w, --watch=PATH ...       Watch path to trigger livereload
  -X, --crossdomain          Set the CORS header Access-Control-Allowed: *
  -x, --exclude=PATTERN ...  Glob pattern for files to exclude from livereload
      --debug                Debugging for devd development
      --version              Show application version.

Args:
  <route>  Routes have the following forms:

                [SUBDOMAIN]/<PATH>=<DIR>
                [SUBDOMAIN]/<PATH>=<URL>
                <DIR>
                <URL>

One of the more fun bits of trivia surrounding this server is the devd.io domain which has an A record that points to IPv4 localhost:

$ dig +short devd.io
127.0.0.1

(this means you can use it with anything that bins to localhost).

miniserve (Rust)

Last, but far from "least" is miniserve, a Rust-based web server with more options than you'll ever truly need:

miniserve 0.22.0
Sven-Hendrik Haase <svenstaro@gmail.com>, Boastful Squirrel <boastful.squirrel@gmail.com>
For when you really just want to serve some files over HTTP right now!

USAGE:
    miniserve [OPTIONS] [--] [PATH]

ARGS:
    <PATH>    Which path to serve

OPTIONS:
    -a, --auth <AUTH>
            Set authentication. Currently supported formats: username:password, username:sha256:hash,
            username:sha512:hash (e.g. joe:123,
            joe:sha256:a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3)

    -c, --color-scheme <COLOR_SCHEME>
            Default color scheme [default: squirrel] [possible values: squirrel, archlinux, zenburn, monokai]

    -d, --color-scheme-dark <COLOR_SCHEME_DARK>
            Default color scheme [default: archlinux] [possible values: squirrel, archlinux, zenburn, monokai]

    -D, --dirs-first
            List directories first

    -F, --hide-version-footer
            Hide version footer

    -g, --enable-tar-gz
            Enable gz-compressed tar archive generation

    -h, --help
            Print help information

    -H, --hidden
            Show hidden files

        --header <HEADER>
            Set custom header for responses

        --hide-theme-selector
            Hide theme selector

    -i, --interfaces <INTERFACES>
            Interface to listen on

        --index <index_file>
            The name of a directory index file to serve, like "index.html"

    -l, --show-symlink-info
            Visualize symlinks in directory listing

    -m, --media-type <MEDIA_TYPE>
            Specify uploadable media types [possible values: image, audio, video]

    -M, --raw-media-type <MEDIA_TYPE_RAW>
            Directly specify the uploadable media type expression

    -o, --overwrite-files
            Enable overriding existing files during file upload

    -p, --port <PORT>
            Port to use [default: 8080]

    -P, --no-symlinks
            Hide symlinks in listing and prevent them from being followed

        --print-completions <shell>
            Generate completion file for a shell [possible values: bash, elvish, fish, powershell, zsh]

        --print-manpage
            Generate man page

    -q, --qrcode
            Enable QR code display

    -r, --enable-tar
            Enable uncompressed tar archive generation

        --random-route
            Generate a random 6-hexdigit route

        --readme
            Enable README.md rendering in directories

        --route-prefix <ROUTE_PREFIX>
            Use a specific route prefix

        --spa
            Activate SPA (Single Page Application) mode

    -t, --title <TITLE>
            Shown instead of host in page title and heading

        --tls-cert <TLS_CERT>
            TLS certificate to use

        --tls-key <TLS_KEY>
            TLS private key to use

    -u, --upload-files [<ALLOWED_UPLOAD_DIR>...]
            Enable file uploading (and optionally specify for which directory)

    -U, --mkdir
            Enable creating directories

    -v, --verbose
            Be verbose, includes emitting access logs

    -V, --version
            Print version information

    -W, --show-wget-footer
            If enabled, display a wget command to recursively download the current directory

    -z, --enable-zip
            Enable zip archive generation

FIN

FWIW, I keep multiple platform binaries of devd and miniserve on a USB stick that is always with me and have them at various dead-drop sites across the internet, including gDrive and other cloud drives your company's security policies gladly let you access. You never know when you're going to "need" to serve up some files.

If you use one of these already or use a different one, drop your experiences in the comments for others to learn from. ☮

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment