composable_tower_http/extract/
any.rs1use super::extractor::Extractor;
2
3#[derive(Debug, Clone)]
4pub struct Any<L, F> {
5 left: L,
6 right: F,
7}
8
9impl<L, F> Any<L, F> {
10 pub const fn new(left: L, right: F) -> Self {
11 Self { left, right }
12 }
13}
14
15impl<L, R> Extractor for Any<L, R>
16where
17 L: Extractor + Send + Sync,
18 R: Extractor + Send + Sync,
19 L::Extracted: From<R::Extracted>,
20 L::Error: Send,
21{
22 type Extracted = L::Extracted;
23
24 type Error = AnyError<L::Error, R::Error>;
25
26 async fn extract(&self, headers: &http::HeaderMap) -> Result<Self::Extracted, Self::Error> {
27 match self.left.extract(headers).await {
28 Ok(extracted) => Ok(extracted),
29 Err(left_error) => match self.right.extract(headers).await {
30 Ok(extracted) => Ok(extracted.into()),
31 Err(right_error) => Err(AnyError {
32 left: left_error,
33 right: right_error,
34 }),
35 },
36 }
37 }
38}
39
40#[derive(Debug, thiserror::Error)]
41#[error("Left: {left}, Right: {right}")]
42pub struct AnyError<L, R> {
43 pub left: L,
44 pub right: R,
45}
46
47#[cfg(feature = "axum")]
48mod axum {
49 use axum::response::{IntoResponse, Response};
50
51 use super::AnyError;
52
53 impl<L, R> IntoResponse for AnyError<L, R>
54 where
55 L: IntoResponse,
56 {
57 fn into_response(self) -> Response {
58 self.left.into_response()
59 }
60 }
61
62 impl<L, R> From<AnyError<L, R>> for Response
63 where
64 L: IntoResponse,
65 {
66 fn from(value: AnyError<L, R>) -> Self {
67 value.into_response()
68 }
69 }
70}