Crates.io | spars-httpd |
lib.rs | spars-httpd |
version | 0.0.1 |
created_at | 2025-08-22 21:32:44.744111+00 |
updated_at | 2025-08-22 21:32:44.744111+00 |
description | A small httpd for serving static files and SPAs |
homepage | |
repository | https://github.com/ckwalsh/spars |
max_upload_size | |
id | 1806967 |
size | 97,302 |
Spars is a lightweight (both binary size and memory usage) HTTP server optimized for safely and securely serving static files and Single Page Applications, particularly within containers.
Spars was written because I was annoyed at seeing so many nginx worker processes in the ps output of my homelab, serving random static websites. decided to use the opportunity to better understand http servers and the Rust language.
mime_guess
cargo feature)Spars is intended for use behind a full-featured http proxy (with logging, etc) for low-qps static sites. It deliberately does not implement:
It is not expected that these features will be added to Spars unless they can be done without increasing binary size and/or memory usage. If you are looking to serve a high-QPS site, or needing any of these features, you should use a well-known httpd (nginx, apache, etc) instead.
wrk -t12 -c12 -d10s http://127.0.0.1:3000/index.html
on my low powered
homelab (AMD Ryzen 7 4800U) and collecting the output from
/proc/<pid>/status
.hyper::http1::Builder::serve_connection()
.Httpd Implementation | QPS | Disk Size | Processes | VmRSS | VmHWM | VmSize | VmPeak |
---|---|---|---|---|---|---|---|
Spars - Plaid + 8kB stack | 267.03 | 136K | 1 | 1396 kB | 1396 kB | 593040 kB | 593136 kB |
Spars - Plaid + musl + 8kB stack | 265.84 | 172K | 1 | 328 kB | 368 kB | 500 kB | 788 kB |
Spars - Docker spars:latest | ^ | 98K | 1 | ^ | ^ | ^ | ^ |
Spars - Release | 266.24 | 644K | 1 | 1372 kB | 1372 kb | 679432 kB | 745064 kB |
Spars - Release + musl | 265.24 | 740K | 1 | 796 kB | 796 kB | 3112 kB | 17644 kB |
Hyper - Plaid | 267.94 | 260K | 1 | 2472 kB | 2472 kB | 1693960 kB | 1759484 kB |
Hyper - Plaid + musl | 267.43 | 304K | 1 | 296 kB | 620 kB | 52412 kB | 52764 kB |
Hyper - Docker spars:examples-hyper | ^ | 148K | 1 | ^ | ^ | ^ | ^ |
Hyper - Release | 268.51 | 988k | 1 | 2992 kB | 2992 kb | 1694796 kB | 1694796 kB |
Hyper - Release + musl | 267.52 | 1.1M | 1 | 984 kB | 1368 kB | 51124 kB | 51480 kB |
Nginx Default Docker Config | - | 21M | 32 | 49864 kB | 51764 kB | 168568 kB | 168568 kB |
Barf: What the hell was that?
Lone Starr: Spaceball 1.
Barf: They've gone to plaid!
~ Spaceballs, 1987
The plaid build profile uses many of the techniques from johnthagen's min-sized-rust repo to optimize the release build, reducing the size of the final binary. This results binaries that are 4x smaller and minimally faster, but makes debugability impossible.
Spars is configured via ENV vars.
ROOT
./public
(/public
within Docker)INDEX_FILE
index.html
FALLBACK_PATH
200 OK
status code/404.html
ALLOW_HIDDEN
.
false
| 0
: Files where any path component starts with .
will not be
servedtrue
| 1
: Files where any path component starts with .
will be
served (DANGER!)wellknown
| Paths starting with /.well-known/
will be served, unless a
following component starts with .
wellknown
ADDR
127.0.0.1
(0.0.0.0
within Docker)PORT
0
, and
accessed by reading the file specified by the ADDR_FILE
var.3000
PID_FILE
ADDR_FILE
<IP>:<PORT>
to this file upon binding the tcp
listenerThis repo includes a Dockerfile for building spars. This Dockerfile:
signal-handler
feature, allowing it to be used as a container
init processesx86_64-unknown-linux-musl
target, producing a static binaryADDR
: 0.0.0.0
PORT
: 3000
ROOT
: /public
INDEX_FILE
: index.html
FALLBACK_PATH
: /404.html
ALLOW_HIDDEN
: wellknown
Planned work: publish spars to DockerHub and link it here.