Skip to content

Commit e788cb1

Browse files
committed
feat: Add support for default
1 parent e2ed959 commit e788cb1

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Implement `std::error::Error` for `AcceptRejection`
13+
- Add support for `Default`
1314

1415
## [0.0.3] - 2025-07-08
1516

axum-accept-macros/src/lib.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ pub fn derive_accept_extractor(input: TokenStream) -> TokenStream {
5959
panic!("AcceptExtractor can only be derived for enums");
6060
};
6161

62+
let has_default = data.variants.iter().any(|variant| {
63+
variant.attrs.iter().any(|attr| match &attr.meta {
64+
Meta::Path(path) => path.is_ident("default"),
65+
_ => false,
66+
})
67+
});
68+
6269
let mut match_arms = Vec::new();
6370

6471
for variant in &data.variants {
@@ -90,12 +97,24 @@ pub fn derive_accept_extractor(input: TokenStream) -> TokenStream {
9097
}
9198
}
9299

100+
let check_and_return_default = if has_default {
101+
Some(quote! {
102+
if mediatypes.is_empty() {
103+
return Ok(#name::default());
104+
}
105+
})
106+
} else {
107+
None
108+
};
109+
93110
let expanded = quote! {
94111
impl #impl_generics axum::extract::FromRequestParts<S> for #name #ty_generics #where_clause {
95112
type Rejection = axum_accept::AcceptRejection;
96113

97114
async fn from_request_parts(parts: &mut axum::http::request::Parts, _state: &S) -> Result<Self, Self::Rejection> {
98-
for mt in axum_accept::parse_mediatypes(&parts.headers)? {
115+
let mediatypes = axum_accept::parse_mediatypes(&parts.headers)?;
116+
#check_and_return_default
117+
for mt in mediatypes {
99118
match (mt.ty.as_str(), mt.subty.as_str(), mt.suffix.map(|s| s.as_str())) {
100119
#(#match_arms)*
101120
_ => {} // continue searching

axum-accept/src/lib.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,33 @@ mod tests {
117117
};
118118
Ok(())
119119
}
120+
121+
#[derive(Debug, AcceptExtractor, Default)]
122+
enum AcceptWithDefault {
123+
#[default]
124+
#[accept(mediatype = "text/plain")]
125+
TextPlain,
126+
#[accept(mediatype = "application/json")]
127+
ApplicationJson,
128+
}
129+
130+
#[tokio::test]
131+
async fn test_accept_extractor_default() -> Result<(), Box<dyn std::error::Error>> {
132+
let req = Request::builder()
133+
.header("accept", "text/csv")
134+
.body(Body::from(""))?;
135+
let state = ();
136+
let media_type = AcceptWithDefault::from_request(req, &state).await;
137+
let Err(AcceptRejection::NoSupportedMediaTypeFound) = media_type else {
138+
panic!("expected no supported media type found")
139+
};
140+
141+
let req = Request::builder().body(Body::from(""))?;
142+
let state = ();
143+
let media_type = AcceptWithDefault::from_request(req, &state).await;
144+
let Ok(AcceptWithDefault::TextPlain) = media_type else {
145+
panic!("expected text/plain (default)")
146+
};
147+
Ok(())
148+
}
120149
}

0 commit comments

Comments
 (0)