# `kcup` `kcup` is a single file server. It responds to every `GET` request it receives with the content of a given file (specified by ENV, CLI argument or STDIN), and for every other request (with any other HTTP method or path) it returns a 404. `kcup` was invented to help with cases where a generally small file needs to be delivered at a certain path, for example [MTA STS's `/.well-known/mta-sts.txt`](https://en.wikipedia.org/wiki/MTA-STS). You can read more about this [on the associated blog post](https://vadosware.io/post/serving-a-single-file-over-http-with-rust-and-go/). **BEWARE** This project and repo is so simple that there aren't even any tests -- I may add some in the future after light use. The machinery (Makefile targets, CI integration, etc) is there for unit, integration and e2e tests, but there just are none. Despite there being no tests, it does "just work" has been benchmarked. Use at your own risk. See also [`kcup-go`](https://gitlab.com/mrman/kcup-go) # Quickstart `kcup` only needs the path to a single file to run: ```console $ kcup -f ``` By default, `kcup` will serve the file at host `127.0.0.1` on port `5000`. `kcup` can also take file content from STDIN like so: ```console $ kcup < your file content > goes here > EOF ``` # Usage ```console kcup 0.1.0 USAGE: kcup [OPTIONS] FLAGS: --help Prints help information -V, --version Prints version information OPTIONS: -f, --file File to read [env: FILE=] -h, --host Host [env: HOST=] [default: 127.0.0.1] -p, --port Port [env: PORT=] [default: 5000] --stdin-read-timeout-seconds Amount of seconds to wait for input on STDIN to serve [env: STDIN_READ_TIMEOUT_SECONDS=] [default: 60] ``` # Environment Variables | ENV variable | Default | Example | Description | |------------------------------|-------------|-------------------------|--------------------------------------------------| | `HOST` | `127.0.0.1` | `0.0.0.0` | The host on which `kcup` will listen | | `PORT` | `5000` | `3000` | The port on whcih `kcup` will listen | | `STDIN_READ_TIMEOUT_SECONDS` | `60` | `10` | The amount of seconds to try and read from STDIN | | `FILE` | N/A | `/path/to/your/file` | The path to the file that will be served | | `TLS_KEY` | N/A | `/path/to/your/tls.key` | Path to a file contains a PEM-encoded TLS key | | `TLS_CERT` | N/A | `/path/to/your/tls.crt` | Path to a file contains CA cert(s) | # Useful Makefile targets The following targets are mostly useful for development, testing the current build, as most depend on `cargo run`. ## Running the current build of `kcup` with HEREDOCs ```console $ make run < > You enter some text > EOF cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.04s Running `target/debug/kcup` [2021-05-09T02:51:58Z INFO kcup] Server configured to run @ [127.0.0.1:5000] [2021-05-09T02:51:58Z INFO kcup] No file path provided, waiting for input on STDIN (max 60 seconds)... [2021-05-09T02:51:58Z INFO kcup] Successfully read input from STDIN [2021-05-09T02:51:58Z INFO kcup] Read [16] characters [2021-05-09T02:51:58Z INFO kcup] Starting HTTP server... ``` ## Serve the example file in the repository ```console $ make example ``` You can serve the example file in the repository with TLS as well ```console $ make example-tls ``` Note that the example page is *NOT* included in the `kcup` binary, you have to bring your own file to serve at production time. # FAQ ## Why is this project named "kcup"? [Keurig created a "K-Cup" brewing system](https://en.wikipedia.org/wiki/Keurig#Keurig_K-Cup_brewing_systems) that has become somewhat infamous. # Alternatives ## `miniserve` **tl;dr `kcup` is about 2x faster than `miniserve`, which is expected as it does much less.** [`miniserve`](https://crates.io/crates/miniserve) is a project that aims to serve files and directories over HTTP that was suggested [on reddit by /u/vlmutolo](https://www.reddit.com/r/rust/comments/m9pe0u/my_weekend_yak_shave_kcup_serves_a_single_file/gsbaxqv/). Since `miniserve` is also capable of serving a single file I've tested it gainst `kcup` with the usual `wrk` command and here are the results tabulated. Roughly by running the following: ```console $ kcup -f /tmp/testfiles/file-1M & $ miniserve /tmp/testfiles/file-1M -p 5001 & $ wrk -t12 -c400 -d30s --latency http://127.0.0.1:5000/any/path/will/work # a few times $ wrk -t12 -c400 -d30s --latency http://127.0.0.1:5001 # a few times ``` | | `kcup` | `miniserve` | |------------------------------------|--------|-------------| | Latency 50% (ms) | 21.09 | 83.94 | | Latency 75% (ms) | 31.04 | 95.73 | | Latency 90% (ms) | 40.81 | 107.23 | | Latency 99% (ms) | 58.54 | 129.38 | | (Thread stats) Latency avg (ms) | 23.29 | 84.94 | | (Thread stats) Latency stddev (ms) | 12.57 | 17.11 | | (Thread stats) Latency max (ms) | 120.18 | 182.87 | | Request/sec | 11,900 | 4599 | | Trasfer/sec (MB) | 1162 | 450 | As you might expect, `kcup` does so little (though there are some feature differences in the overlap) that it performs roughly 2x as well as `miniserve`. I did not limit the processes and my machine is pretty beefy: 6 physical cores (12 hyper threads) and 32GB of RAM so these processes got as much room as they cared to use.