1mod api;
2mod assets;
3
4use crate::error::{ChronicleError, Result};
5use crate::git::CliOps;
6
7pub fn serve(git_ops: CliOps, port: u16, open_browser: bool) -> Result<()> {
8 let addr = format!("0.0.0.0:{port}");
9 let server = tiny_http::Server::http(&addr).map_err(|e| ChronicleError::Config {
10 message: format!("failed to start web server on {addr}: {e}"),
11 location: snafu::Location::default(),
12 })?;
13
14 println!("Chronicle web viewer: http://localhost:{port}");
15 if open_browser {
16 open::that(format!("http://localhost:{port}")).ok();
17 }
18
19 for request in server.incoming_requests() {
20 let url = request.url().to_string();
21 let result = if url.starts_with("/api/") {
22 api::handle(&git_ops, &url)
23 } else {
24 Ok(assets::handle(&url))
25 };
26
27 match result {
28 Ok(response) => {
29 request.respond(response).ok();
30 }
31 Err(e) => {
32 let body = serde_json::json!({ "error": e.to_string() }).to_string();
33 let response = tiny_http::Response::from_string(body)
34 .with_header(
35 tiny_http::Header::from_bytes(
36 &b"Content-Type"[..],
37 &b"application/json"[..],
38 )
39 .unwrap(),
40 )
41 .with_status_code(500);
42 request.respond(response).ok();
43 }
44 }
45 }
46
47 Ok(())
48}