Serve Files Embedded In A Rust Binary With axum
Introduction
This is how I'm embedding files in a Rust binary and servering them with axum. Doing so means it's not necessary to have them on the file system when the server is run.
---
[dependencies]
axum = "0.8.0"
tokio = { version = "1.44.2", features = ["macros", "rt-multi-thread"] }
---
use axum::{Router, response::Html, routing::get};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(serve_home_page));
let listener = tokio::net::TcpListener::bind("0.0.0.0:4545").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn serve_home_page() -> Html<&'static str> {
let response = include_str!("files/index.html");
Html(response)
}
A Directory
(Note that you can't do this for the root of the site)
---
[dependencies]
axum = "0.8.0"
axum-embed = "0.1.0"
rust-embed = "8.7.0"
tokio = { version = "1.44.2", features = ["macros", "rt-multi-thread"] }
---
use axum::{Router, response::Html, routing::get};
use axum_embed::{FallbackBehavior, ServeEmbed};
use rust_embed::RustEmbed;
#[derive(RustEmbed, Clone)]
#[folder = "src/assets"]
struct Assets;
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(serve_home_page)).nest_service(
"/assets",
ServeEmbed::<Assets>::with_parameters(None, FallbackBehavior::NotFound, None),
);
let listener = tokio::net::TcpListener::bind("0.0.0.0:4545").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn serve_home_page() -> Html<&'static str> {
let response = r#"<!DOCTYPE html>
<html>
<body>
<h1>Hello, World!</h1>
</body>
</html>"#;
Html(response)
}
-
The home page is served via it's own route so it can be set independently.
-
URLs that start with
/assets
are served from the src/assets
directory from the source files.
-
During development the
src/assets
files are served from the file system. When the binary is built, they get embedded
-
TBD if this works with tower's live reload