|
use crate::{ |
|
app::{ |
|
constant::{ |
|
AUTHORIZATION_BEARER_PREFIX, CONTENT_TYPE_TEXT_HTML_WITH_UTF8, |
|
CONTENT_TYPE_TEXT_PLAIN_WITH_UTF8, ROUTE_LOGS_PATH, |
|
}, |
|
lazy::AUTH_TOKEN, |
|
model::{AppConfig, AppState, PageContent, RequestLog}, |
|
}, |
|
common::{model::ApiStatus, utils::extract_token}, |
|
}; |
|
use axum::{ |
|
body::Body, |
|
extract::State, |
|
http::{ |
|
header::{AUTHORIZATION, CONTENT_TYPE}, |
|
HeaderMap, StatusCode, |
|
}, |
|
response::{IntoResponse, Response}, |
|
Json, |
|
}; |
|
use chrono::Local; |
|
use std::sync::Arc; |
|
use tokio::sync::Mutex; |
|
|
|
|
|
pub async fn handle_logs() -> impl IntoResponse { |
|
match AppConfig::get_page_content(ROUTE_LOGS_PATH).unwrap_or_default() { |
|
PageContent::Default => Response::builder() |
|
.header(CONTENT_TYPE, CONTENT_TYPE_TEXT_HTML_WITH_UTF8) |
|
.body(Body::from( |
|
include_str!("../../../static/logs.min.html").to_string(), |
|
)) |
|
.unwrap(), |
|
PageContent::Text(content) => Response::builder() |
|
.header(CONTENT_TYPE, CONTENT_TYPE_TEXT_PLAIN_WITH_UTF8) |
|
.body(Body::from(content.clone())) |
|
.unwrap(), |
|
PageContent::Html(content) => Response::builder() |
|
.header(CONTENT_TYPE, CONTENT_TYPE_TEXT_HTML_WITH_UTF8) |
|
.body(Body::from(content.clone())) |
|
.unwrap(), |
|
} |
|
} |
|
|
|
pub async fn handle_logs_post( |
|
State(state): State<Arc<Mutex<AppState>>>, |
|
headers: HeaderMap, |
|
) -> Result<Json<LogsResponse>, StatusCode> { |
|
let auth_token = AUTH_TOKEN.as_str(); |
|
|
|
|
|
let auth_header = headers |
|
.get(AUTHORIZATION) |
|
.and_then(|h| h.to_str().ok()) |
|
.and_then(|h| h.strip_prefix(AUTHORIZATION_BEARER_PREFIX)) |
|
.ok_or(StatusCode::UNAUTHORIZED)?; |
|
|
|
let state = state.lock().await; |
|
|
|
|
|
if auth_header == auth_token { |
|
return Ok(Json(LogsResponse { |
|
status: ApiStatus::Success, |
|
total: state.total_requests, |
|
active: Some(state.active_requests), |
|
error: Some(state.error_requests), |
|
logs: state.request_logs.clone(), |
|
timestamp: Local::now().to_string(), |
|
})); |
|
} |
|
|
|
|
|
let token_part = extract_token(auth_header).ok_or(StatusCode::UNAUTHORIZED)?; |
|
|
|
|
|
let filtered_logs: Vec<RequestLog> = state |
|
.request_logs |
|
.iter() |
|
.filter(|log| log.token_info.token == token_part) |
|
.cloned() |
|
.collect(); |
|
|
|
|
|
if filtered_logs.is_empty() { |
|
return Err(StatusCode::UNAUTHORIZED); |
|
} |
|
|
|
Ok(Json(LogsResponse { |
|
status: ApiStatus::Success, |
|
total: filtered_logs.len() as u64, |
|
active: None, |
|
error: None, |
|
logs: filtered_logs, |
|
timestamp: Local::now().to_string(), |
|
})) |
|
} |
|
|
|
#[derive(serde::Serialize)] |
|
pub struct LogsResponse { |
|
pub status: ApiStatus, |
|
pub total: u64, |
|
#[serde(skip_serializing_if = "Option::is_none")] |
|
pub active: Option<u64>, |
|
#[serde(skip_serializing_if = "Option::is_none")] |
|
pub error: Option<u64>, |
|
pub logs: Vec<RequestLog>, |
|
pub timestamp: String, |
|
} |
|
|