use axum::{extract::State, response::Html, routing::get, Router};
use rusty_ssr::prelude::*;
use std::sync::Arc;
use tracing_subscriber;
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let args: Vec<String> = std::env::args().collect();
let mut builder = SsrEngine::builder()
.bundle_path("ssr-bundle.js")
.pool_size(num_cpus::get())
.cache_size(300)
.cache_ttl_secs(300);
if let Some(pos) = args.iter().position(|a| a == "--template") {
if let Some(path) = args.get(pos + 1) {
builder = builder.html_template(path);
tracing::info!("📄 Using HTML template: {}", path);
}
}
if let Some(pos) = args.iter().position(|a| a == "--manifest") {
if let Some(path) = args.get(pos + 1) {
builder = builder.assets_manifest(path);
tracing::info!("📦 Using Vite manifest: {}", path);
}
}
let engine = builder
.build_engine()
.expect("Failed to create SSR engine");
let engine = Arc::new(engine);
let app = Router::new()
.route("/", get(index_handler))
.route("/*path", get(ssr_handler))
.with_state(engine);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await
.unwrap();
tracing::info!("🚀 Server running on http://localhost:3000");
axum::serve(listener, app).await.unwrap();
}
async fn index_handler(State(engine): State<Arc<SsrEngine>>) -> Html<String> {
match engine.render_to_html("/").await {
Ok(html) => Html(html),
Err(e) => Html(format!("<h1>Error</h1><pre>{}</pre>", e)),
}
}
async fn ssr_handler(
State(engine): State<Arc<SsrEngine>>,
axum::extract::Path(path): axum::extract::Path<String>,
) -> Html<String> {
let url = format!("/{}", path);
match engine.render_to_html(&url).await {
Ok(html) => Html(html),
Err(e) => Html(format!("<h1>Error</h1><pre>{}</pre>", e)),
}
}