From d9125314809e7f03cb155f91d535e94da583a365 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Tue, 31 Jan 2023 22:21:19 -0500 Subject: custosm avatars and banners --- src/types/extract.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 4 deletions(-) (limited to 'src/types/extract.rs') 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 FromRequest for Png +where + B: HttpBody + Sync + Send + 'static, + B::Data: Send, + B::Error: Into, + S: Send + Sync, +{ + type Rejection = Response; + + async fn from_request(req: Request, state: &S) -> Result { + + 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(pub T); #[async_trait] @@ -150,7 +181,43 @@ pub trait Check { } } -pub async fn parse_body(mut req: Request, state: &S) -> Result +async fn read_body(mut req: Request, state: &S) -> Result> +where + B: HttpBody + Sync + Send + 'static, + B::Data: Send, + B::Error: Into, + S: Send + Sync, +{ + + let Ok(ClientIp(ip)) = req.extract_parts::().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::() + .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(mut req: Request, state: &S) -> Result 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 { -- cgit v1.2.3-freya