Updating the Readme and License files.

This commit is contained in:
Elf M. Sternberg 2026-06-06 13:25:57 -07:00
parent 8a3dc6995c
commit 2c516fec96
2 changed files with 98 additions and 0 deletions

18
LICENSE.md Normal file
View File

@ -0,0 +1,18 @@
Copyright (c) 2026 Elf M. Sternberg
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

80
README.md Normal file
View File

@ -0,0 +1,80 @@
# tower-http-servezip
ServeZip is a [Rust](https://rust-lang.org/)
[Tower](https://github.com/tower-rs/tower) leaf service that serves files from a
given Zip file. The Zip file can either be specified by a Pathbuf or a `static
&[u8]`; the latter is intended to allow you to embed your Zip file directly into
the binary, creating a complete standalone solution for a deployable web
service. You just need to supply the logic.
## Usage
The `demo` folder contains a somewhat complete implementation, including a demo
zip file. **TODO** Full indexing is not currently implemented. The demo can be started via:
``` sh
cargo run -p demo -- --zip demo/assets/demo.zip
```
Valid targets are: `http://localhost:8001/index.html`, `hello.txt`, and
`docs/just-a-file.txt`. These demonstrate the basics of mime-types,
content-length, and file lookup. Any other file should return a simple 404.
## Internals
Interally, this is a mess. It was a project-based learning exercise, and like so
much of my career now I'm not sure I could reimplement it without the book open
and the lots of example code.
I'm mostly unhappy with the fact that I have to make a copy of whatever stream
I'm sending out over the wire, rather than pulling it sequentially from the Zip
file while it's decompressing. This is mostly intended to supply a PWA and its
back-end logic in a single package; it shouldn't be doing work that often, but
it still annoys me that I have to do it more than once while (briefly) wasting
memory. I wish I understond Rust well enough to say "Either let me keep wasting
the memory and keep the performance, or let me take the performance hit without
wasting the memory."
But I'm not that good at Rust quite yet.
## Lessons learned
There's a lot going on here, and I'm still not entirely thrilled with how it
went down. I *am* proud of figuring out how to use the NewType pattern to create
an implementation of ServeZip that works with `Arc[u8]`, which is the data type
I pass around containing the compresed data. Reading
[ServeDir's](https://github.com/tower-rs/tower-http/tree/main/tower-http/src/services/fs/serve_dir)
source code opened my eyes to a lot of the little bits, like separating the
Config, the Builder, the Service; I have some old habits about keeping
everything really close at hand, but Rust makes the implentation so smooth and
efficient that I'm really starting to appreciate how it works.
This implementation just unpacks the Zip file *every time*. I was hoping for
something smarter, maybe a way to just keep separate ZipCursors alive and
re-usable, but for now this will have to do. It's not bad, it just feels like
there's a lot of Rust to learn before it's much more idiomatic.
Huge shoutout to @bearcave [[Bearcove](https://github.com/bearcove)]] for the
sans-io implementation of Zip in Rust. I learned a lot about sans-io in the
process, even if I didn't end up using much of it this time.
## Todo
- Implement full indexing
- Implement ServeDir's use of http::body, instead of axum
- Read ServeDir much more closely in order to understand what it's doing
internally; all the security and safety issues, plus performance
- Reduce the amount of copying. Oy, the copying
- Put an upper limit on Zip size, configurable from the command line
- Provide a `build.rs` file in the demo to show how `include_bytes!` works
## License
Tower-http-servezip is Copyright [Elf M. Sternberg](https://elfsternberg.com)
(c) 2026, and licensed under the original [MIT License](./LICENSE.md). A copy of
the license file is included in the root folder.
## An all-human effort.
Every last line of this code I typed myself. No AI-provided code included. I
wouldn't have learned anything otherwise. Just sayin'.