use crate::{ auth::Session, runtime::{ApiError, App}, settings::PanelCompression, }; use axum::{ extract::{rejection::JsonRejection, State}, response::{Html, IntoResponse, Response}, Extension, }; use http::{HeaderMap, StatusCode}; use std::sync::{Arc, OnceLock}; use super::panel_content::PanelContent; static ADMIN_INDEX: OnceLock = OnceLock::new(); fn panel_response(headers: &HeaderMap, compression: &PanelCompression) -> Response { let content = ADMIN_INDEX.get_or_init(|| { let (metrics, web_metrics) = include_str!("../web/partials/overview-metrics.html") .split_once("") .expect("invalid Overview metrics partial"); let (charts, web_charts) = include_str!("../web/partials/overview-charts.html") .split_once("") .expect("invalid Overview charts partial"); let html = include_str!("../web/index.html") .replace("", metrics) .replace("", charts) .replace("", web_metrics) .replace("", web_charts) .replace("__RUSTPROXY_ASSET_ID__", super::asset_build_id()) .replace("__RUSTPROXY_VERSION__", env!("CARGO_PKG_VERSION")); PanelContent::new(Box::leak(html.into_boxed_str())) }); content.response(headers, compression, "text/html; charset=utf-8") } pub(super) async fn index( State(state): State>, session: Option>, headers: HeaderMap, ) -> Response { if session.is_none() { let html = include_str!("../web/login.html") .replace("__RUSTPROXY_ASSET_ID__", super::asset_build_id()); return Html(html).into_response(); } let snapshot = state.config.load(); panel_response( &headers, &snapshot.envelope.config.administration.panel_compression, ) } pub(super) fn invalid_json(error: JsonRejection) -> ApiError { let status = match error.status() { StatusCode::PAYLOAD_TOO_LARGE => StatusCode::PAYLOAD_TOO_LARGE, StatusCode::UNSUPPORTED_MEDIA_TYPE => StatusCode::UNSUPPORTED_MEDIA_TYPE, _ => StatusCode::BAD_REQUEST, }; ApiError(status, "auth.invalid_request".into()) } #[cfg(test)] mod tests;