diff --git a/src/main.rs b/src/main.rs index 0c68abb..57511f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ use std::net::SocketAddr; use crate::routes::{ - absolute_handler, fallback_handler, favicon_handler, implicit_handler, index_handler, - relative_handler, + absolute_handler, fallback_handler, favicon_handler, favicon_png_handler, implicit_handler, + index_handler, relative_handler, }; use axum::{http::HeaderValue, response::Response, routing::get, Router}; use config::Configuration; @@ -36,6 +36,7 @@ async fn main() { let app = Router::new() .route("/", get(index_handler)) .route("/favicon.ico", get(favicon_handler)) + .route("/favicon.png", get(favicon_png_handler)) .route("/{path}", get(implicit_handler)) .route("/rel/{path}", get(relative_handler)) .route("/relative/{path}", get(relative_handler)) diff --git a/src/routes.rs b/src/routes.rs index 92dbe63..0190f4b 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -83,6 +83,27 @@ pub async fn favicon_handler(ConnectInfo(addr): ConnectInfo) -> impl } } +/// Handles `/favicon.png` - generates a dynamic clock favicon showing the current time. +/// +/// Logs the client IP address and returns a PNG image of an analog clock. +pub async fn favicon_png_handler(ConnectInfo(addr): ConnectInfo) -> impl IntoResponse { + let now = chrono::Utc::now(); + + // Log the IP address for the favicon request + tracing::info!("Favicon PNG request from IP: {}", addr.ip()); + + // Generate PNG bytes directly + match generate_favicon_png_bytes(now) { + Ok(png_bytes) => ( + StatusCode::OK, + [(header::CONTENT_TYPE, "image/png")], + png_bytes, + ) + .into_response(), + Err(e) => get_error_response(e).into_response(), + } +} + /// Fallback handler for unmatched routes. pub async fn fallback_handler() -> impl IntoResponse { get_error_response(TimeBannerError::NotFound).into_response()