|
1 | | -use actix_files as fs; |
2 | | -use actix_web::{web, App, Error as WebError, HttpResponse, HttpServer}; |
| 1 | +#[macro_use] |
| 2 | +extern crate rust_embed; |
| 3 | + |
| 4 | +use actix_web::body::Body; |
| 5 | +use actix_web::{web, App, Error as WebError, HttpRequest, HttpResponse, HttpServer}; |
3 | 6 | use futures::TryFutureExt; |
4 | 7 | use local_ip; |
| 8 | +use mime_guess::from_path; |
5 | 9 | use r2d2_sqlite::{self, SqliteConnectionManager}; |
6 | 10 | use serde_json; |
| 11 | +use std::borrow::Cow; |
7 | 12 | use std::io; |
8 | 13 |
|
9 | 14 | mod db; |
10 | 15 | mod dolphin; |
11 | 16 | use db::Pool; |
12 | 17 |
|
| 18 | +#[derive(RustEmbed)] |
| 19 | +#[folder = "ui/build/"] |
| 20 | +struct UIAsset; |
| 21 | + |
| 22 | +#[derive(RustEmbed)] |
| 23 | +#[folder = "docs/"] |
| 24 | +struct DocAsset; |
| 25 | + |
13 | 26 | async fn list_streams(db: web::Data<Pool>) -> Result<HttpResponse, WebError> { |
14 | 27 | let pool = db.clone(); |
15 | 28 |
|
@@ -47,38 +60,77 @@ async fn insert_data( |
47 | 60 | Ok(HttpResponse::Ok().finish()) |
48 | 61 | } |
49 | 62 |
|
50 | | -async fn p404() -> Result<fs::NamedFile, WebError> { |
51 | | - Ok(fs::NamedFile::open("ui/build/index.html")?.set_status_code(actix_web::http::StatusCode::OK)) |
| 63 | +fn handle_ui_file(path: &str) -> HttpResponse { |
| 64 | + match UIAsset::get(path) { |
| 65 | + Some(content) => { |
| 66 | + let body: Body = match content { |
| 67 | + Cow::Borrowed(bytes) => bytes.into(), |
| 68 | + Cow::Owned(bytes) => bytes.into(), |
| 69 | + }; |
| 70 | + HttpResponse::Ok() |
| 71 | + .content_type(from_path(path).first_or_octet_stream().as_ref()) |
| 72 | + .body(body) |
| 73 | + } |
| 74 | + None => handle_ui_file("index.html"), |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +fn handle_doc_file(path: &str) -> HttpResponse { |
| 79 | + match DocAsset::get(path) { |
| 80 | + Some(content) => { |
| 81 | + let body: Body = match content { |
| 82 | + Cow::Borrowed(bytes) => bytes.into(), |
| 83 | + Cow::Owned(bytes) => bytes.into(), |
| 84 | + }; |
| 85 | + HttpResponse::Ok() |
| 86 | + .content_type(from_path(path).first_or_octet_stream().as_ref()) |
| 87 | + .body(body) |
| 88 | + } |
| 89 | + None => HttpResponse::NotFound().body("404 Not Found"), |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +fn ui(req: HttpRequest) -> HttpResponse { |
| 94 | + let path = &req.path()["/".len()..]; |
| 95 | + handle_ui_file(path) |
| 96 | +} |
| 97 | + |
| 98 | +fn docs_index(_req: HttpRequest) -> HttpResponse { |
| 99 | + handle_doc_file("index.html") |
| 100 | +} |
| 101 | + |
| 102 | +fn docs(req: HttpRequest) -> HttpResponse { |
| 103 | + let path = &req.path()["/api/v1/docs/".len()..]; |
| 104 | + handle_doc_file(path) |
52 | 105 | } |
53 | 106 |
|
54 | 107 | #[actix_rt::main] |
55 | 108 | async fn main() -> io::Result<()> { |
56 | 109 | let manager = SqliteConnectionManager::file("dlphn.db"); |
57 | 110 | let pool = Pool::new(manager).unwrap(); |
58 | 111 |
|
59 | | - // create the table if needed |
60 | 112 | db::create_table(pool.get().unwrap()).unwrap(); |
61 | | - |
62 | | - // Start http server |
63 | 113 | dolphin::logo(); |
| 114 | + |
64 | 115 | let ip = local_ip::get().unwrap(); |
65 | 116 | println!("[dlphn] UI available at http://{}:8080", ip.to_string()); |
66 | 117 | println!( |
67 | 118 | "[dlphn] API docs available at: http://{}:8080/api/v1/docs", |
68 | 119 | ip.to_string() |
69 | 120 | ); |
| 121 | + |
70 | 122 | HttpServer::new(move || { |
71 | 123 | App::new() |
72 | 124 | .data(pool.clone()) |
73 | | - .service(fs::Files::new("/api/v1/docs", "docs").index_file("index.html")) |
| 125 | + .service(web::resource("/api/v1/docs").route(web::get().to(docs_index))) |
| 126 | + .service(web::resource("/api/v1/docs/{_:.*}").route(web::get().to(docs))) |
74 | 127 | .service(web::resource("/api/v1/streams").route(web::get().to(list_streams))) |
75 | 128 | .service( |
76 | 129 | web::resource("/api/v1/streams/{key}/data") |
77 | 130 | .route(web::get().to(list_data)) |
78 | 131 | .route(web::post().to(insert_data)), |
79 | 132 | ) |
80 | | - .service(fs::Files::new("/", "ui/build").index_file("index.html")) |
81 | | - .default_service(web::resource("").route(web::get().to(p404))) |
| 133 | + .service(web::resource("/{_:.*}").route(web::get().to(ui))) |
82 | 134 | }) |
83 | 135 | .bind("0.0.0.0:8080")? |
84 | 136 | .run() |
|
0 commit comments