eggserve
EggServe is a hardened, HTTP-correct static file server and reusable Rust HTTP/static-serving library, with a Python
http.server-shaped facade.
The CLI serves static files only. The Python package provides hardened static
serving plus a bounded, synchronous custom-handler path shaped like
http.server. The Rust crate exposes a low-level, embeddable HTTP runtime and
service boundary. EggServe itself is not an application framework, ASGI/WSGI
runtime, proxy, or general-purpose socketserver replacement.
Why EggServe instead of python -m http.server?
python -m http.server is a useful local-development tool, but its ordinary
defaults bind broadly, follow symlinks, serve dotfiles, and list directories.
EggServe makes loopback binding, path confinement, dotfile denial, and disabled
directory listings the defaults; weaker behavior requires an explicit opt-in.
It also provides native range and conditional responses, bounded resource
limits, and the same hardened static service behind its CLI, Python, and Rust
surfaces.
The concise surface comparison is in the Python compatibility contract.
CLI quickstart
Serve the small example fixture on loopback:
For a source checkout, the equivalent is:
Make a public bind explicit when serving beyond the local machine:
The positional form is eggserve [OPTIONS] [PORT] [DIRECTORY]. Explicit port
sources occupy the PORT slot, so a numeric directory remains unambiguous after
them—for example, eggserve --port 9000 1234 serves directory 1234. Use
--directory 1234 when selecting a numeric directory without a positional
port; a single positional numeric token continues to mean PORT.
The CLI is a static file server. Directory listings, symlink following, and
dotfile serving are separate explicit flags. Static metadata can be set with
--content-type and repeatable -H/--header; see the CLI reference
and security policy.
Python http.server facade
The canonical Python static-serving example is
examples/python_http_server_static.py.
Run it with python examples/python_http_server_static.py; it is source-
familiar while keeping the filesystem and transport in Rust.
Stock SimpleHTTPRequestHandler with the documented default eligibility uses
the native static fast path. Directory listings, dotfiles, and symlinks remain
denied unless explicitly enabled through the supported facade settings.
The Python 3.15-shaped static metadata hooks are supported: set
default_content_type for unknown suffixes and pass ordered
extra_response_headers through a stock handler or functools.partial.
Extra headers are emitted only on final 200 static responses and cannot
override runtime-owned metadata. See
examples/python_custom_headers.py for a
working demonstration.
For bounded synchronous custom responses, use the complete
examples/python_custom_handler.py. The
optional subprocess lifecycle example is
examples/python_subprocess.py; it is not the
canonical http.server replacement.
When the tls feature is available, HTTPS serving uses
HTTPSServer / ThreadingHTTPSServer — see
examples/python_https_server.py.
Custom handlers are synchronous and receive bounded in-memory rfile/wfile
facades. They do not receive raw sockets, do not provide unbounded streaming,
and do not turn EggServe into an application server. The optional subprocess
helpers are under eggserve.subprocess; the primary API is eggserve.server.
See the Python API reference for the full six-class
surface and the compatibility contract
for intentional deviations from the stdlib.
Rust library
eggserve-core is the intended Rust library crate for the 0.x line. It
exposes primitives as the semver-considered public facade and server as an
experimental transport-owning runtime; there is no additional eggserve
facade crate. Rust applications do not need a direct Hyper dependency.
The concise static-server flow is:
use ;
# async
The executable, mechanically checked examples are the static server, the custom service, and the primitives demo. They use public EggServe modules only, include readiness plus graceful shutdown, and are the recommended starting points for custom services.
The runtime owns listeners, HTTP/1 parsing, framing, timeouts, and lifecycle;
Service owns request handling and response construction. The server module
is experimental before 1.0. See the Rust architecture overview,
primitives facade, and
runtime contract.
Security and compatibility boundaries
- Loopback bind, no symlinks, no dotfiles, and no directory listing are the safe defaults for static serving.
- Static serving is GET/HEAD only and rejects request bodies; custom services may opt into bounded bodies under the runtime ceiling.
- Path traversal and symlink escape are denied at library level. Unix safe defaults use descriptor-relative resolution; Windows is qualified for the executed handle-relative classes but remains trusted/local-content only.
- HTTP/1.1, ranges, conditional requests, canonical response normalization, and bounded resource admission are part of the implemented contract.
- The CLI accepts hostnames in
--bind, repeatable safe-H/--headerstatic metadata, and--content-type; TLS accepts a combined cert/key PEM when--tls-keyis omitted. - Raw socket ownership,
translate_path(), arbitrarySSLContexthandling, async Python handlers, unbounded Python response streaming, and ASGI/WSGI are intentionally unavailable.
See the security policy, threat model, Python compatibility matrix, and non-goals.
Installation
# Python wheel: CPython 3.11+; Linux, macOS, and Windows wheels are built
# according to the support matrix.
# From source (requires a Rust toolchain)
The source-checkout command installs the eggserve-bin package's eggserve
binary. Rust embedders should add eggserve-core as their library dependency;
the executable crate is intentionally a thin CLI surface.
The Python wheel includes the native extension and extension-backed CLI entry point; it does not bundle a second standalone CLI binary. See toolchain and wheel support.
Deeper references
CLI and installation:
- CLI reference — all flags, positional parsing, and examples
- TLS support — building with
--features tls, certificate requirements - Toolchain and wheel support — platform matrix, Python versions
- Deployment guidance — production profiles, reverse-proxy patterns
Python:
- Python API reference —
HTTPServer,ThreadingHTTPServer,HTTPSServer, handler classes - Python compatibility contract — deviations from
http.server - Python packaging — wheel architecture, build from source
- Request body migration — body modes, one-shot enforcement, error hierarchy
Rust library:
- Rust HTTP primitives — HTTP/1.1 primitive contract
- Public API boundary — stability tiers, semver policy
- Library capability matrix — cross-surface feature inventory
Security:
- Security policy — safe defaults and enforcement
- Threat model — attacker profiles, trust boundaries
- Security review — posture summary for adopters
- Non-goals — explicit exclusions
Architecture:
- Architecture overview — workspace layout, module map, data flow
- Examples — all runnable demonstrations
Local verification
The routine CI workflow has separate Rust and Python jobs. Platform qualification and release certification are manual workflows; see the release process.