diff options
Diffstat (limited to 'src/types/extract.rs')
-rw-r--r-- | src/types/extract.rs | 74 |
1 files changed, 70 insertions, 4 deletions
diff --git a/src/types/extract.rs b/src/types/extract.rs index 50c413b..54f250a 100644 --- a/src/types/extract.rs +++ b/src/types/extract.rs @@ -1,4 +1,4 @@ -use std::io::Read; +use std::io::{Read, Cursor}; use axum::{ async_trait, @@ -10,6 +10,7 @@ use axum::{ }; use axum_client_ip::ClientIp; use bytes::Bytes; +use image::{io::Reader, ImageFormat, DynamicImage}; use serde::de::DeserializeOwned; use tower_cookies::Cookies; @@ -99,6 +100,36 @@ where } } +pub struct Png(pub DynamicImage); + +#[async_trait] +impl<S, B> FromRequest<S, B> for Png +where + B: HttpBody + Sync + Send + 'static, + B::Data: Send, + B::Error: Into<BoxError>, + S: Send + Sync, +{ + type Rejection = Response; + + async fn from_request(req: Request<B>, state: &S) -> Result<Self> { + + let bytes = match read_body(req, state).await { + Ok(body) => body, + Err(err) => return Err(err), + }; + + let mut reader = Reader::new(Cursor::new(bytes)); + reader.set_format(ImageFormat::Png); + + let Ok(img) = reader.decode() else { + return Err(ResponseCode::BadRequest.text("Failed to decode png image")) + }; + + Ok(Self(img)) + } +} + pub struct Json<T>(pub T); #[async_trait] @@ -150,7 +181,43 @@ pub trait Check { } } -pub async fn parse_body<S, B>(mut req: Request<B>, state: &S) -> Result<String> +async fn read_body<S, B>(mut req: Request<B>, state: &S) -> Result<Vec<u8>> +where + B: HttpBody + Sync + Send + 'static, + B::Data: Send, + B::Error: Into<BoxError>, + S: Send + Sync, +{ + + let Ok(ClientIp(ip)) = req.extract_parts::<ClientIp>().await else { + tracing::error!("Failed to read client ip"); + return Err(ResponseCode::InternalServerError.text("Failed to read client ip")); + }; + + let method = req.method().clone(); + let uri = req.uri().clone(); + let path = req + .extensions() + .get::<RouterURI>() + .map_or("", |path| path.0); + + let Ok(bytes) = Bytes::from_request(req, state).await else { + return Err(ResponseCode::BadRequest.text("Request can be at most 512kb")); + }; + + console::log( + ip, + method, + uri, + Some(path.to_string()), + None, + ) + .await; + + Ok(bytes.bytes().flatten().collect()) +} + +async fn parse_body<S, B>(mut req: Request<B>, state: &S) -> Result<String> where B: HttpBody + Sync + Send + 'static, B::Data: Send, @@ -170,8 +237,7 @@ where .map_or("", |path| path.0); let Ok(bytes) = Bytes::from_request(req, state).await else { - tracing::error!("Failed to read request body"); - return Err(ResponseCode::InternalServerError.text("Failed to read request body")); + return Err(ResponseCode::BadRequest.text("Request can be at most 512kb")); }; let Ok(body) = String::from_utf8(bytes.bytes().flatten().collect()) else { |