recipes/backend/src/ron_extractor.rs
2025-04-28 23:22:38 +02:00

51 lines
1.5 KiB
Rust

//! An Axum extractor for HTTP body containing RON data (Rusty Object Notation).
use axum::{
body::Bytes,
extract::{FromRequest, Request},
http::{StatusCode, header},
response::{IntoResponse, Response},
};
use serde::de::DeserializeOwned;
use crate::ron_utils;
pub struct ExtractRon<T: DeserializeOwned>(pub T);
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))
}
}