ctoolbox/io/webui/
flexible_form.rs1use axum::extract::{FromRequest, Request};
10use axum_extra::extract::{Form, FormRejection};
11use axum_typed_multipart::{
12 TryFromMultipartWithState, TypedMultipart, TypedMultipartError,
13};
14
15pub struct FlexibleForm<T>(pub T);
16
17#[derive(Debug)]
19pub struct UnsupportedContentTypeRejection {
20 pub error: String,
21}
22
23#[derive(Debug)]
25pub enum FlexibleFormRejection {
26 Multipart(TypedMultipartError),
27 Form(FormRejection),
28 UnsupportedContentType(UnsupportedContentTypeRejection),
29}
30
31impl<T, S> FromRequest<S> for FlexibleForm<T>
32where
33 T: TryFromMultipartWithState<S> + serde::de::DeserializeOwned,
34 S: Send + Sync,
35{
36 type Rejection = FlexibleFormRejection;
37
38 async fn from_request(
40 req: Request,
41 state: &S,
42 ) -> Result<Self, Self::Rejection> {
43 let content_type = req
44 .headers()
45 .get(axum::http::header::CONTENT_TYPE)
46 .and_then(|v| v.to_str().ok())
47 .unwrap_or("");
48
49 match content_type {
50 "application/x-www-form-urlencoded" => {
51 match Form::<T>::from_request(req, state).await {
53 Ok(Form(data)) => Ok(FlexibleForm(data)),
54 Err(form_err) => Err(FlexibleFormRejection::Form(form_err)),
55 }
56 }
57 ct if ct.starts_with("multipart/form-data") => {
58 match TypedMultipart::<T>::from_request(req, state).await {
60 Ok(TypedMultipart(data)) => Ok(FlexibleForm(data)),
61 Err(multipart_err) => {
62 Err(FlexibleFormRejection::Multipart(multipart_err))
63 }
64 }
65 }
66 &_ => Err(FlexibleFormRejection::UnsupportedContentType(
67 UnsupportedContentTypeRejection {
68 error: "Unsupported content type".into(),
69 },
70 )),
71 }
72 }
73}
74
75impl axum::response::IntoResponse for FlexibleFormRejection {
77 fn into_response(self) -> axum::response::Response {
78 match self {
79 FlexibleFormRejection::Multipart(e) => e.into_response(),
80 FlexibleFormRejection::Form(e) => e.into_response(),
81 FlexibleFormRejection::UnsupportedContentType(e) => {
82 use axum::http::StatusCode;
83 (StatusCode::UNSUPPORTED_MEDIA_TYPE, e.error).into_response()
84 }
85 }
86 }
87}