Use server state to reuse HTTP client.
This commit is contained in:
parent
192f0e757a
commit
c813356eaa
56
src/main.rs
56
src/main.rs
|
@ -2,7 +2,8 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
body::BoxBody,
|
body::BoxBody,
|
||||||
http::header,
|
extract::State,
|
||||||
|
http::header::{self, HeaderMap},
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
routing::get,
|
routing::get,
|
||||||
Router,
|
Router,
|
||||||
|
@ -12,6 +13,11 @@ use serde::Deserialize;
|
||||||
use tracing::{info, Level};
|
use tracing::{info, Level};
|
||||||
use tracing_subscriber::{filter::Targets, layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{filter::Targets, layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct ServerState {
|
||||||
|
client: reqwest::Client,
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let filter = Targets::from_str(std::env::var("RUST_LOG").as_deref().unwrap_or("info"))
|
let filter = Targets::from_str(std::env::var("RUST_LOG").as_deref().unwrap_or("info"))
|
||||||
|
@ -23,7 +29,11 @@ async fn main() {
|
||||||
.with(filter)
|
.with(filter)
|
||||||
.init();
|
.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();
|
let addr = "0.0.0.0:8080".parse().unwrap();
|
||||||
info!("Listening on {addr}");
|
info!("Listening on {addr}");
|
||||||
|
@ -33,8 +43,8 @@ async fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn root_get() -> Response<BoxBody> {
|
async fn root_get(_headers: HeaderMap, State(state): State<ServerState>) -> Response<BoxBody> {
|
||||||
match get_cat_ascii_art().await {
|
match get_cat_ascii_art(&state.client).await {
|
||||||
Ok(art) => (
|
Ok(art) => (
|
||||||
StatusCode::OK,
|
StatusCode::OK,
|
||||||
[(header::CONTENT_TYPE, "text/html; charset=utf-8")],
|
[(header::CONTENT_TYPE, "text/html; charset=utf-8")],
|
||||||
|
@ -48,14 +58,30 @@ async fn root_get() -> Response<BoxBody> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_cat_ascii_art() -> color_eyre::Result<String> {
|
async fn get_cat_ascii_art(client: &reqwest::Client) -> color_eyre::Result<String> {
|
||||||
|
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<String> {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct CatImage {
|
struct CatImage {
|
||||||
url: String,
|
url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
let api_url = "https://api.thecatapi.com/v1/images/search";
|
let api_url = "https://api.thecatapi.com/v1/images/search";
|
||||||
let client = reqwest::Client::default();
|
|
||||||
|
|
||||||
let image = client
|
let image = client
|
||||||
.get(api_url)
|
.get(api_url)
|
||||||
|
@ -66,22 +92,16 @@ async fn get_cat_ascii_art() -> color_eyre::Result<String> {
|
||||||
.await?
|
.await?
|
||||||
.pop()
|
.pop()
|
||||||
.ok_or_else(|| color_eyre::eyre::eyre!("The Cat API returned no images"))?;
|
.ok_or_else(|| color_eyre::eyre::eyre!("The Cat API returned no images"))?;
|
||||||
|
Ok(image.url)
|
||||||
|
}
|
||||||
|
|
||||||
let image_bytes = client
|
async fn download_file(client: &reqwest::Client, url: &str) -> color_eyre::Result<Vec<u8>> {
|
||||||
.get(image.url)
|
let bytes = client
|
||||||
|
.get(url)
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.error_for_status()?
|
.error_for_status()?
|
||||||
.bytes()
|
.bytes()
|
||||||
.await?;
|
.await?;
|
||||||
|
Ok(bytes.to_vec())
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue