home ~ projects ~ socials

Serve A Local Directory As A Static Web Site In Rust

This is old code. Check out:

https://github.com/alanwsmith/servedir

until I can get it updated.

Introduction

This is the basic code to server a directory as a website that will do an automatic hot reload when files change.

```cargo
[dependencies]
axum = "0.8.1"
notify = "8.0.0"
tokio = { version = "1.43.0", features = ["rt-multi-thread", "macros"] }
tower-http = { version = "0.6.2", features = ["fs"] }
tower-livereload = "0.9.6"
```

use axum::response::Html;
use axum::routing::get;
use axum::Router;
use notify::Watcher;
use std::path::Path;
use tower_http::services::ServeDir;
use tower_livereload::LiveReloadLayer;

#[tokio::main]
async fn main() {
    let dir_to_serve = Path::new(".");
    let livereload = LiveReloadLayer::new();
    let reloader = livereload.reloader();
    let service = ServeDir::new(dir_to_serve)
        .append_index_html_on_directories(true)
        .not_found_service(get(|| missing_page()));
    let app = Router::new().fallback_service(service).layer(livereload);
    let mut watcher = notify::recommended_watcher(move |_| reloader.reload()).unwrap();
    watcher
        .watch(Path::new(dir_to_serve), notify::RecursiveMode::Recursive)
        .unwrap();
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3993").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

async fn missing_page() -> Html<&'static str> {
    Html(
        r#"<!DOCTYPE html>
<html>
<head><style>body { background: black; color: white;}</style></head>
<body>Page Not Found</body>
</html>"#,
    )
}

Notes

  • The directory that's served is defined in the dir_to_serve variable
  • index.html files are served if a path leads to a directory and the index.html file exists.
  • A 404 Page Not Found is returned if no index.html file exist.
  • This is a lot like browser-sync but with way fewer features
  • The main reason I running this is so I don't have to also run browser-sync at the same time. I just start up my app and it provides the core functionality as well as the web page

TODOs

    [] Figure out how debouncing works or if it needs to be added.

-- end of line --

References

This is basically what I used for the sample

The docs say that using a fallback_service isn't optimal. It's what the example uses though. So, I'm going with it.