recipes/backend/src/ron_extractor.rs
2024-12-04 17:39:56 +01:00

52 lines
1.4 KiB
Rust

use axum::{
async_trait,
body::Bytes,
extract::{FromRequest, Request},
http::{header, StatusCode},
response::{IntoResponse, Response},
};
use serde::de::DeserializeOwned;
use crate::ron_utils;
pub struct ExtractRon<T: DeserializeOwned>(pub T);
#[async_trait]
impl<S, T> FromRequest<S> for ExtractRon<T>
where
S: Send + Sync,
T: DeserializeOwned,
{
type Rejection = Response;
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
match req.headers().get(header::CONTENT_TYPE) {
Some(content_type) => {
if content_type != ron_utils::RON_CONTENT_TYPE {
return Err(ron_utils::ron_error(
StatusCode::BAD_REQUEST,
&format!(
"Invalid content type, must be {:?}",
ron_utils::RON_CONTENT_TYPE
),
)
.into_response());
}
}
None => {
return Err(
ron_utils::ron_error(StatusCode::BAD_REQUEST, "No content type given")
.into_response(),
)
}
}
let body = Bytes::from_request(req, state)
.await
.map_err(IntoResponse::into_response)?;
let ron = ron_utils::parse_body(body)?;
Ok(Self(ron))
}
}