minor modification

This commit is contained in:
guochao 2024-02-27 10:42:11 +08:00
parent a6c0f916b7
commit 7a9b3aba6a
Signed by: guochao
GPG Key ID: 79F7306D2AA32FC3

View File

@ -2,7 +2,8 @@ use std::sync::Arc;
use axum::{ use axum::{
extract::State, extract::State,
response::{ErrorResponse, Html, Redirect}, http::{HeaderMap, HeaderValue},
response::{ErrorResponse, Html, IntoResponse, Redirect},
routing::{get, post, IntoMakeService}, routing::{get, post, IntoMakeService},
Json, Router, Json, Router,
}; };
@ -10,27 +11,64 @@ use serde::Serialize;
use tokio::sync::RwLock; use tokio::sync::RwLock;
use crate::{ use crate::{
web::templates::load_templates, task::{collect_local_address, MY_ADDRESS},
types::{AppState, PageContext}, types::{AppState, PageContext},
task::{MY_ADDRESS, collect_local_address}, web::templates::load_templates,
}; };
async fn root(State(state): State<Arc<RwLock<AppState>>>) -> axum::response::Result<Html<String>> { enum Response<T> {
let state = state.read().await; Html(Html<String>),
Json(Json<T>),
}
impl<T> IntoResponse for Response<T>
where
T: Serialize,
{
fn into_response(self) -> axum::response::Response {
match self {
Response::Html(html) => html.into_response(),
Response::Json(json) => json.into_response(),
}
}
}
#[derive(Serialize, Default)]
struct AddressResult {
address: String,
}
async fn root(
State(state): State<Arc<RwLock<AppState>>>,
headers: HeaderMap,
) -> axum::response::Result<Response<AddressResult>> {
let address_guard = MY_ADDRESS.lock().await; let address_guard = MY_ADDRESS.lock().await;
let address = address_guard.clone(); let address = address_guard.clone();
drop(address_guard); drop(address_guard);
let ctx = match tera::Context::from_serialize(&PageContext { let accept: Vec<&str> = headers
address, .get("Accept")
}) { .map(|h| h.to_str().unwrap())
Ok(ctx) => ctx, .unwrap_or("text/html")
Err(err) => return Err(ErrorResponse::from(format!("{err}"))), .split(",")
}; .collect();
match state.templates.render("index.html", &ctx) {
Ok(result) => Ok(Html::from(result)), tracing::info!(?accept, "accept");
Err(err) => Err(ErrorResponse::from(format!("{err}"))), if accept.contains(&"text/html") {
let state = state.read().await;
let ctx = match tera::Context::from_serialize(&PageContext { address }) {
Ok(ctx) => ctx,
Err(err) => return Err(ErrorResponse::from(format!("{err}"))),
};
match state.templates.render("index.html", &ctx) {
Ok(result) => Ok(Response::Html(Html::from(result))),
Err(err) => Err(ErrorResponse::from(format!("{err}"))),
}
} else if accept.contains(&"application/json") {
Ok(Response::Json(Json(AddressResult { address })))
} else {
unreachable!()
} }
} }
@ -40,7 +78,9 @@ struct ReloadResult {
error: Option<String>, error: Option<String>,
} }
async fn reload(State(state): State<Arc<RwLock<AppState>>>) -> Result<Redirect, Json<ReloadResult>> { async fn reload(
State(state): State<Arc<RwLock<AppState>>>,
) -> Result<Redirect, Json<ReloadResult>> {
let mut state = state.write_owned().await; let mut state = state.write_owned().await;
if let Err(err) = state.templates.full_reload() { if let Err(err) = state.templates.full_reload() {
return Err(Json(ReloadResult { return Err(Json(ReloadResult {
@ -59,7 +99,7 @@ async fn reload(State(state): State<Arc<RwLock<AppState>>>) -> Result<Redirect,
pub fn make_service() -> Result<IntoMakeService<Router<()>>, Box<dyn std::error::Error>> { pub fn make_service() -> Result<IntoMakeService<Router<()>>, Box<dyn std::error::Error>> {
let templates = load_templates()?; let templates = load_templates()?;
let router = Router::new(); let router = Router::new();
#[cfg(feature = "serve-static")] #[cfg(feature = "serve-static")]