First commit in rust
This commit is contained in:
65
backchannel-server/src/http/server.rs
Normal file
65
backchannel-server/src/http/server.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
use anyhow::{Context, Result};
|
||||
use axum::body::Body;
|
||||
use axum::extract::Path;
|
||||
use axum::http::{header, HeaderValue, StatusCode};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use mime_guess::from_path;
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "../backchannel-web/dist"]
|
||||
struct WebAssets;
|
||||
|
||||
pub async fn serve(bind_addr: &str) -> Result<()> {
|
||||
let app = Router::new()
|
||||
.route("/", get(index))
|
||||
.route("/*path", get(asset_or_index));
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(bind_addr)
|
||||
.await
|
||||
.with_context(|| format!("Failed to bind HTTP server to {bind_addr}"))?;
|
||||
|
||||
tracing::info!("BackChannel web UI listening on http://{bind_addr}");
|
||||
axum::serve(listener, app).await.context("HTTP server failed")
|
||||
}
|
||||
|
||||
async fn index() -> Response {
|
||||
render_asset("index.html")
|
||||
}
|
||||
|
||||
async fn asset_or_index(Path(path): Path<String>) -> Response {
|
||||
if path.is_empty() {
|
||||
return render_asset("index.html");
|
||||
}
|
||||
|
||||
render_asset(&path)
|
||||
}
|
||||
|
||||
fn render_asset(path: &str) -> Response {
|
||||
let canonical = path.trim_start_matches('/');
|
||||
|
||||
if let Some(content) = WebAssets::get(canonical) {
|
||||
return build_response(canonical, content.data.as_ref(), StatusCode::OK);
|
||||
}
|
||||
|
||||
if let Some(index) = WebAssets::get("index.html") {
|
||||
return build_response("index.html", index.data.as_ref(), StatusCode::OK);
|
||||
}
|
||||
|
||||
(StatusCode::NOT_FOUND, "Web UI asset not found").into_response()
|
||||
}
|
||||
|
||||
fn build_response(path: &str, body: &[u8], status: StatusCode) -> Response {
|
||||
let mime = from_path(path).first_or_octet_stream();
|
||||
|
||||
let mut response = Response::new(Body::from(body.to_vec()));
|
||||
*response.status_mut() = status;
|
||||
response.headers_mut().insert(
|
||||
header::CONTENT_TYPE,
|
||||
HeaderValue::from_str(mime.as_ref()).unwrap_or(HeaderValue::from_static("application/octet-stream")),
|
||||
);
|
||||
|
||||
response
|
||||
}
|
||||
Reference in New Issue
Block a user