69 lines
1.6 KiB
Rust
69 lines
1.6 KiB
Rust
use axum::{
|
|
async_trait,
|
|
extract::FromRequestParts,
|
|
http::{
|
|
header::{HeaderValue, ACCEPT},
|
|
request::Parts,
|
|
StatusCode,
|
|
},
|
|
};
|
|
|
|
/// Extractor for the Accept header
|
|
pub struct ExtractAccept(pub HeaderValue);
|
|
|
|
#[async_trait]
|
|
impl<S> FromRequestParts<S> for ExtractAccept
|
|
where
|
|
S: Send + Sync,
|
|
{
|
|
type Rejection = (StatusCode, &'static str);
|
|
|
|
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
|
|
if let Some(accept) = parts.headers.get(ACCEPT) {
|
|
Ok(ExtractAccept(accept.clone()))
|
|
} else {
|
|
Err((StatusCode::NOT_ACCEPTABLE, "`Accept` header is missing"))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Supported content types
|
|
pub(super) enum ResponseType {
|
|
Html,
|
|
Json,
|
|
}
|
|
|
|
/// Parses the Accept header and returns content type to return
|
|
pub(super) fn parse_accept(accept: &HeaderValue) -> ResponseType {
|
|
let bytes = accept.as_bytes();
|
|
if bytes.starts_with(b"application/json") {
|
|
return ResponseType::Json;
|
|
}
|
|
ResponseType::Html
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use axum::{
|
|
extract::FromRequest,
|
|
http::{HeaderValue, Request},
|
|
};
|
|
|
|
use super::*;
|
|
|
|
#[tokio::test]
|
|
async fn test_accept() {
|
|
let req = Request::builder()
|
|
.header(ACCEPT, "application/json; charset=utf-8")
|
|
.body(())
|
|
.unwrap();
|
|
|
|
let extract = ExtractAccept::from_request(req, &()).await.unwrap();
|
|
|
|
assert_eq!(
|
|
extract.0,
|
|
HeaderValue::from_static("application/json; charset=utf-8")
|
|
);
|
|
}
|
|
}
|