ddoc/
server.rs

1//! nothing yet
2use {
3    crate::*,
4    rouille::Response,
5    std::path::PathBuf,
6};
7
8pub struct Server {
9    base_url: String,
10    addr: String,
11    static_path: PathBuf,
12}
13
14impl Server {
15    pub fn new(
16        static_path: PathBuf,
17        port: u16,
18    ) -> DdResult<Self> {
19        let addr = format!("localhost:{port}");
20        let base_url = format!("http://{addr}/");
21        Ok(Self {
22            base_url,
23            addr,
24            static_path,
25        })
26    }
27    pub fn base_url(&self) -> &str {
28        &self.base_url
29    }
30    pub fn run(self) -> DdResult<()> {
31        let static_path = self.static_path;
32        let rouille_server = rouille::Server::new(self.addr, move |request| {
33            // build the file path
34            let mut path = static_path.clone();
35            path.push(&request.url()[1..]); // Remove leading /
36
37            if path.is_dir() {
38                if request.url().ends_with('/') {
39                    // If it's a directory with trailing /,
40                    // the URL is correct but we must send index.html
41                    path.push("index.html");
42                    if path.exists() {
43                        if let Ok(file) = std::fs::File::open(&path) {
44                            return Response::from_file("text/html", file);
45                        }
46                    }
47                } else {
48                    // The URL is missing a trailing /
49                    let new_url = format!("{}/", request.url());
50                    return Response::redirect_301(new_url);
51                }
52            }
53
54            // Try to serve the file
55            rouille::match_assets(request, &static_path)
56        })
57        .map_err(|e| DdError::Server(e.to_string()))?;
58        rouille_server.run();
59        Ok(())
60    }
61}