diff --git a/src/main.rs b/src/main.rs index bdb6840..5adb3e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,8 @@ use std::str::FromStr; use axum::{ body::BoxBody, - http::header, + extract::State, + http::header::{self, HeaderMap}, response::{IntoResponse, Response}, routing::get, Router, @@ -12,6 +13,11 @@ use serde::Deserialize; use tracing::{info, Level}; use tracing_subscriber::{filter::Targets, layer::SubscriberExt, util::SubscriberInitExt}; +#[derive(Clone)] +struct ServerState { + client: reqwest::Client, +} + #[tokio::main] async fn main() { let filter = Targets::from_str(std::env::var("RUST_LOG").as_deref().unwrap_or("info")) @@ -23,7 +29,11 @@ async fn main() { .with(filter) .init(); - let app = Router::new().route("/", get(root_get)); + let state = ServerState { + client: Default::default(), + }; + + let app = Router::new().route("/", get(root_get)).with_state(state); let addr = "0.0.0.0:8080".parse().unwrap(); info!("Listening on {addr}"); @@ -33,8 +43,8 @@ async fn main() { .unwrap(); } -async fn root_get() -> Response { - match get_cat_ascii_art().await { +async fn root_get(_headers: HeaderMap, State(state): State) -> Response { + match get_cat_ascii_art(&state.client).await { Ok(art) => ( StatusCode::OK, [(header::CONTENT_TYPE, "text/html; charset=utf-8")], @@ -48,14 +58,30 @@ async fn root_get() -> Response { } } -async fn get_cat_ascii_art() -> color_eyre::Result { +async fn get_cat_ascii_art(client: &reqwest::Client) -> color_eyre::Result { + let image_url = get_cat_image_url(client).await?; + + let image_bytes = download_file(client, &image_url).await?; + + let image = image::load_from_memory(&image_bytes)?; + + let ascii_art = artem::convert( + image, + artem::options::OptionBuilder::new() + .target(artem::options::TargetType::HtmlFile(true, true)) + .build(), + ); + + Ok(ascii_art) +} + +async fn get_cat_image_url(client: &reqwest::Client) -> color_eyre::Result { #[derive(Deserialize)] struct CatImage { url: String, } let api_url = "https://api.thecatapi.com/v1/images/search"; - let client = reqwest::Client::default(); let image = client .get(api_url) @@ -66,22 +92,16 @@ async fn get_cat_ascii_art() -> color_eyre::Result { .await? .pop() .ok_or_else(|| color_eyre::eyre::eyre!("The Cat API returned no images"))?; + Ok(image.url) +} - let image_bytes = client - .get(image.url) +async fn download_file(client: &reqwest::Client, url: &str) -> color_eyre::Result> { + let bytes = client + .get(url) .send() .await? .error_for_status()? .bytes() .await?; - - let image = image::load_from_memory(&image_bytes)?; - let ascii_art = artem::convert( - image, - artem::options::OptionBuilder::new() - .target(artem::options::TargetType::HtmlFile(true, true)) - .build(), - ); - - Ok(ascii_art) + Ok(bytes.to_vec()) }