relay_server/extractors/
remote.rs

1//! Extractors for types from other crates via [`Remote`].
2
3use axum::extract::{FromRequest, Request};
4use axum::http::StatusCode;
5use axum::response::{IntoResponse, Response};
6use multer::Multipart;
7
8use crate::service::ServiceState;
9use crate::utils::{self, ApiErrorResponse};
10
11/// A transparent wrapper around a remote type that implements [`FromRequest`] or [`IntoResponse`].
12///
13/// # Example
14///
15/// ```ignore
16/// use std::convert::Infallible;
17///
18/// use axum::extract::{FromRequest, Request};
19/// use axum::response::IntoResponse;
20///
21/// use crate::extractors::Remote;
22///
23/// // Derive `FromRequest` for `bool` for illustration purposes:
24/// impl<S> axum::extract::FromRequest<S> for Remote<bool> {
25///     type Rejection = Remote<Infallible>;
26///
27///     async fn from_request(request: Request) -> Result<Self, Self::Rejection> {
28///         Ok(Remote(true))
29///     }
30/// }
31///
32/// impl IntoResponse for Remote<Infallible> {
33///    fn into_response(self) -> axum::response::Response {
34///        match self.0 {}
35///    }
36/// }
37/// ```
38#[derive(Debug)]
39pub struct Remote<T>(pub T);
40
41impl<T> From<T> for Remote<T> {
42    fn from(inner: T) -> Self {
43        Self(inner)
44    }
45}
46
47impl FromRequest<ServiceState> for Remote<Multipart<'static>> {
48    type Rejection = Remote<multer::Error>;
49
50    async fn from_request(
51        request: Request,
52        _state: &ServiceState,
53    ) -> Result<Self, Self::Rejection> {
54        utils::multipart_from_request(request, multer::Constraints::new())
55            .map(Remote)
56            .map_err(Remote)
57    }
58}
59
60impl IntoResponse for Remote<multer::Error> {
61    fn into_response(self) -> Response {
62        let Self(ref error) = self;
63
64        let status_code = match error {
65            multer::Error::FieldSizeExceeded { .. } => StatusCode::PAYLOAD_TOO_LARGE,
66            multer::Error::StreamSizeExceeded { .. } => StatusCode::PAYLOAD_TOO_LARGE,
67            _ => StatusCode::BAD_REQUEST,
68        };
69
70        (status_code, ApiErrorResponse::from_error(error)).into_response()
71    }
72}