51 lines
1.5 KiB
Rust
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))
|
|
}
|
|
}
|