Crate web_static_pack
source ·Expand description
web-static-pack
Embed static resources (GUI, assets, images, styles, html) within executable. Serve with hyper or any server of your choice.
Usage scenario:
- Combines given directory tree into single, fast, binary-based single-file representation, called
pack
. Use simple CLI toolweb-static-pack-packer
to create a pack. - Pack could be embedded into your application using
include_bytes!
single macro. - Super-fast, zero-copy
loader
provides by-name access to files. - Easy-to-use
hyper_loader
allows super-quick integration with hyper-based server.
Features:
- Super fast, low overhead
- 100% ’static access, zero data copy
- 100% pack-time calculated
Content-Type
,ETag
(using sha3) - 100% pack-time calculated gzip-compressed files
- Almost no external dependencies
Limitations:
- By default all files with guesses text/ content type are treated as utf-8
- Packs are not guaranteed to be portable across versions / architectures
Future goals:
- You tell me
Non-Goals:
- Directory listings
- automatic index.html resolving
- Uploads
Example:
- Create a pack from
cargo doc
:
$ cargo doc --no-deps
$ cargo run ./target/doc/ docs.pack
- Serve docs.pack from your web-application (see
examples/docs
)
use anyhow::{Context, Error};
use hyper::{
service::{make_service_fn, service_fn},
Body, Request, Response, Server,
};
use lazy_static::lazy_static;
use log::LevelFilter;
use simple_logger::SimpleLogger;
use std::{convert::Infallible, include_bytes, net::SocketAddr};
use web_static_pack::{hyper_loader::Responder, loader::Loader};
#[tokio::main]
async fn main() {
SimpleLogger::new()
.env()
.with_level(LevelFilter::Info)
.init()
.unwrap();
main_result().await.unwrap()
}
async fn service(request: Request<Body>) -> Result<Response<Body>, Infallible> {
lazy_static! {
static ref PACK: &'static [u8] = include_bytes!("docs.pack");
static ref LOADER: Loader = Loader::new(&PACK).unwrap();
static ref RESPONDER: Responder<'static> = Responder::new(&LOADER);
}
Ok(RESPONDER.request_respond(&request))
}
async fn main_result() -> Result<(), Error> {
let address = SocketAddr::from(([0, 0, 0, 0], 8080));
let server = Server::bind(&address).serve(make_service_fn(|_connection| async {
Ok::<_, Infallible>(service_fn(service))
}));
log::info!("Server listening on {:?}", address);
server.await.context("server")?;
Ok(())
}
Modules
- Hyper integration. See examples/docs/main.rs for usage sample.
- Main loader module. This is the part you should include in you target project if you want to read packs directly. After creating a pack with cli packer tool, include this into your program with
include_bytes!
macro. Then pass it toLoader::new()
. Files may be retrieved usingget()
method.