venus_server/
embedded_frontend.rs

1//! Embedded frontend assets for Venus server.
2//!
3//! This module provides embedded static files for the Venus notebook UI.
4//! It is only available when the `embedded-frontend` feature is enabled.
5
6use axum::{
7    body::Body,
8    http::{header, Response, StatusCode},
9};
10use rust_embed::Embed;
11
12/// Embedded frontend assets.
13#[derive(Embed)]
14#[folder = "src/frontend/"]
15pub struct FrontendAssets;
16
17/// Serve an embedded frontend file.
18pub fn serve_static(path: String) -> Response<Body> {
19    // Remove leading slash if present
20    let path = path.strip_prefix('/').map(|s| s.to_string()).unwrap_or(path);
21
22    match FrontendAssets::get(&path) {
23        Some(content) => {
24            let mime = mime_guess::from_path(&path)
25                .first_or_octet_stream()
26                .to_string();
27
28            Response::builder()
29                .status(StatusCode::OK)
30                .header(header::CONTENT_TYPE, mime)
31                .header(header::CACHE_CONTROL, "no-cache, no-store, must-revalidate")
32                .body(Body::from(content.data.into_owned()))
33                .unwrap()
34        }
35        None => Response::builder()
36            .status(StatusCode::NOT_FOUND)
37            .body(Body::from("Not Found"))
38            .unwrap(),
39    }
40}
41
42/// Serve the main index.html file.
43pub fn serve_index() -> Response<Body> {
44    serve_static("index.html".to_string())
45}
46
47/// Check if the frontend assets are available.
48pub fn is_available() -> bool {
49    FrontendAssets::get("index.html").is_some()
50}
51
52/// List all embedded files (for debugging).
53pub fn list_files() -> Vec<String> {
54    FrontendAssets::iter().map(|s| s.to_string()).collect()
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn test_frontend_assets_available() {
63        assert!(is_available(), "index.html should be embedded");
64    }
65
66    #[test]
67    fn test_list_files() {
68        let files = list_files();
69        assert!(files.iter().any(|f| f == "index.html"));
70        assert!(files.iter().any(|f| f == "app.js"));
71        assert!(files.iter().any(|f| f == "styles.css"));
72        assert!(files.iter().any(|f| f == "graph.js"));
73        assert!(files.iter().any(|f| f == "lsp-client.js"));
74    }
75}