1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
use std::convert::Infallible;
use axum::{
extract::FromRequestParts,
http::{header, request::Parts},
};
use crate::ContentType;
/// Extractor for the request's desired response [`ContentType`].
///
/// # Examples
///
/// ```edition2021
/// # use axum_codec::{Accept, Codec};
/// # use axum::{http::HeaderValue, response::IntoResponse};
/// # use serde::Serialize;
/// #
/// #[axum_codec::apply(encode)]
/// struct User {
/// name: String,
/// age: u8,
/// }
///
/// fn get_user(accept: Accept) -> impl IntoResponse {
/// Codec(User {
/// name: "Alice".into(),
/// age: 42,
/// })
/// .to_response(accept)
/// }
/// #
/// # fn main() {}
/// ```
#[derive(Debug, Clone, Copy)]
pub struct Accept(ContentType);
impl Accept {
/// Returns the request's desired response [`ContentType`].
#[inline]
#[must_use]
pub fn content_type(self) -> ContentType {
self.0
}
}
impl From<Accept> for ContentType {
#[inline]
fn from(accept: Accept) -> Self {
accept.0
}
}
#[axum::async_trait]
impl<S> FromRequestParts<S> for Accept
where
S: Send + Sync + 'static,
{
type Rejection = Infallible;
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
let header = None
.or_else(|| parts.headers.get(header::ACCEPT))
.or_else(|| parts.headers.get(header::CONTENT_TYPE))
.and_then(ContentType::from_header)
.unwrap_or_default();
Ok(Self(header))
}
}