iota_rest_api/
content_type.rs1use axum::http::{self, HeaderMap, StatusCode, header};
6use mime::Mime;
7use tap::Pipe;
8
9#[derive(Debug, Clone)]
11pub struct ContentType(pub Mime);
12
13impl ContentType {
14 pub fn from_headers(headers: &HeaderMap) -> Option<Self> {
15 parse_content_type(headers).ok()?.map(Self)
16 }
17}
18
19fn parse_content_type(headers: &HeaderMap) -> Result<Option<Mime>, mime::FromStrError> {
20 let Some(header) = headers
21 .get(header::CONTENT_TYPE)
22 .and_then(|hval| hval.to_str().ok())
23 else {
24 return Ok(None);
25 };
26
27 let mime: Mime = header.parse()?;
28 Ok(Some(mime))
29}
30
31#[axum::async_trait]
32impl<S> axum::extract::FromRequestParts<S> for ContentType
33where
34 S: Send + Sync,
35{
36 type Rejection = (StatusCode, &'static str);
37
38 async fn from_request_parts(
39 parts: &mut http::request::Parts,
40 _: &S,
41 ) -> Result<Self, Self::Rejection> {
42 parse_content_type(&parts.headers)
43 .map_err(|_| (StatusCode::BAD_REQUEST, "invalid Content-Type mime"))?
44 .ok_or((StatusCode::BAD_REQUEST, "Content-Type header missing"))?
45 .pipe(Self)
46 .pipe(Ok)
47 }
48}