|
| 1 | +# Axum Version Analysis |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +The goal of this rewrite was not to mechanically translate the old `iron` code, but to replace it with an `axum` implementation while keeping the CLI and the main runtime behavior aligned as closely as practical, with a smaller direct dependency surface. |
| 6 | + |
| 7 | +The default direct dependencies are: |
| 8 | + |
| 9 | +- `axum 0.8.8` |
| 10 | +- `clap 4.6.0` |
| 11 | +- `tokio 1.50.0` |
| 12 | +- `flate2 1.1.9` |
| 13 | +- `mime_guess 2.0.5` |
| 14 | +- `httpdate 1.0.3` |
| 15 | +- `base64 0.22.1` |
| 16 | +- `time 0.3.47` |
| 17 | + |
| 18 | +When the `tls` feature is enabled, it additionally pulls in: |
| 19 | + |
| 20 | +- `openssl 0.10.76` |
| 21 | +- `tokio-openssl 0.6.5` |
| 22 | + |
| 23 | +`clap` intentionally does not use `derive`, and TLS is intentionally behind a single `tls` feature that is disabled by default. |
| 24 | + |
| 25 | +## Benefits |
| 26 | + |
| 27 | +- The server now sits on a maintained async stack instead of the old `iron` ecosystem. |
| 28 | +- The direct dependency surface is smaller and easier to reason about. |
| 29 | +- TLS uses `axum::serve` with a custom listener instead of adding `axum-server`. |
| 30 | +- The codebase is split into focused modules for config, server setup, handlers, and utilities. |
| 31 | +- The default build does not carry OpenSSL or TLS glue code. |
| 32 | + |
| 33 | +## Tradeoffs and Pitfalls |
| 34 | + |
| 35 | +### 1. TLS is optional, but when enabled it uses system OpenSSL |
| 36 | + |
| 37 | +To keep the default build smaller, TLS is disabled unless `tls` is enabled. |
| 38 | + |
| 39 | +Impact: |
| 40 | + |
| 41 | +- Default builds are smaller and compile faster. |
| 42 | +- TLS-capable builds depend on system OpenSSL compatibility. |
| 43 | +- `--cert` still uses PKCS#12, which keeps CLI behavior aligned but keeps TLS on the OpenSSL path. |
| 44 | + |
| 45 | +### 2. File responses are streamed |
| 46 | + |
| 47 | +Regular file responses and compressed file responses are streamed instead of buffering the entire file. |
| 48 | + |
| 49 | +Impact: |
| 50 | + |
| 51 | +- Memory usage is much lower for large files. |
| 52 | +- Compressed responses still use a background thread per streamed file response. |
| 53 | + |
| 54 | +### 3. Uploads are streamed to temporary files |
| 55 | + |
| 56 | +Uploads are written to temporary files first, then moved into place after CSRF validation succeeds. |
| 57 | + |
| 58 | +Impact: |
| 59 | + |
| 60 | +- Large uploads do not need to sit fully in memory. |
| 61 | +- Failed CSRF validation cleans up temporary files. |
| 62 | + |
| 63 | +### 4. `base-url` is normalized |
| 64 | + |
| 65 | +`--base-url` is normalized to start with `/`, and to end with `/` when it is not root. |
| 66 | + |
| 67 | +Impact: |
| 68 | + |
| 69 | +- Inputs like `prefix`, `/prefix`, and `/prefix/` all normalize to `/prefix/`. |
| 70 | + |
| 71 | +### 5. `--try-file` semantics are explicit |
| 72 | + |
| 73 | +- Relative paths are resolved against the server root. |
| 74 | +- Absolute paths are used as-is. |
| 75 | + |
| 76 | +This is more explicit than the old behavior and matches the current help text. |
| 77 | + |
| 78 | +### 6. HEAD + compression is cleaner, not identical |
| 79 | + |
| 80 | +The old middleware-based compression path had some inconsistent historical behavior for `HEAD`. |
| 81 | + |
| 82 | +The current implementation does not preserve those quirks: |
| 83 | + |
| 84 | +- `HEAD` does not read and compress the whole file just to compute a compressed length. |
| 85 | +- The result is cleaner HTTP behavior, but not byte-for-byte historical parity in that edge case. |
| 86 | + |
| 87 | +## Compatibility Summary |
| 88 | + |
| 89 | +### Kept aligned |
| 90 | + |
| 91 | +- CLI flags and short options |
| 92 | +- Directory listing |
| 93 | +- `--index` |
| 94 | +- `--upload` / `--csrf` |
| 95 | +- `--auth` |
| 96 | +- `--redirect` |
| 97 | +- `--nocache` |
| 98 | +- `--norange` |
| 99 | +- `--cors` |
| 100 | +- `--coop` / `--coep` |
| 101 | +- `--compress` |
| 102 | +- `--try-file` |
| 103 | +- `--base-url` |
| 104 | +- `--cert` / `--certpass` with PKCS#12 |
| 105 | + |
| 106 | +### Intentional fixes |
| 107 | + |
| 108 | +- `--open` uses `https://` when TLS is enabled |
| 109 | +- Error pages escape injected text |
| 110 | +- `--cors` responds to `OPTIONS` preflight requests |
| 111 | +- `--upload-size-limit` supports human-readable values such as `30K`, `50M`, and `1G`, interpreted with powers of 1024 |
| 112 | + |
| 113 | +## Verification |
| 114 | + |
| 115 | +The current replacement is covered by black-box HTTP tests for: |
| 116 | + |
| 117 | +- directory listing |
| 118 | +- `try-file` |
| 119 | +- basic auth |
| 120 | +- range requests |
| 121 | +- cache revalidation |
| 122 | +- CORS preflight |
| 123 | +- upload with CSRF |
| 124 | +- gzip compression |
| 125 | + |
| 126 | +Both default and `tls` builds pass `cargo test` and `cargo clippy`. |
0 commit comments