1
- pub mod v2;
2
- // testing v2 impl...
3
- /*
4
- use std::task::{Context, Poll};
5
-
6
- use axum::http::{self, StatusCode};
7
- use axum::response::IntoResponse;
8
- use futures_util::future::BoxFuture;
1
+ use std:: {
2
+ convert:: Infallible ,
3
+ future:: Future ,
4
+ pin:: Pin ,
5
+ task:: { Context , Poll } ,
6
+ } ;
7
+
8
+ use axum:: {
9
+ extract:: Request ,
10
+ http:: StatusCode ,
11
+ response:: { IntoResponse , Response } ,
12
+ } ;
13
+ use pin_project:: pin_project;
9
14
use tower:: { Layer , Service } ;
10
15
11
- use crate::serve::auth::Authenticator ;
16
+ use crate :: principal :: Principal ;
12
17
18
+ pub trait Authenticate {
19
+ // how to implementor fill this associate type
20
+ // need impl trait in associate type ?
21
+ // https://github.com/rust-lang/rust/issues/63063
22
+ type Output : Future < Output = Result < Principal , ( ) > > ;
23
+
24
+ fn authenticate ( & self , token : Option < String > ) -> Self :: Output ;
25
+ }
26
+
27
+ #[ pin_project( project = AuthFutureProj ) ]
28
+ pub enum AuthenticateFuture < AuthFut , S , F > {
29
+ Authenticate {
30
+ req : Option < Request > ,
31
+ #[ pin]
32
+ auth_fut : AuthFut ,
33
+ inner : S ,
34
+ } ,
35
+ ServiceCall {
36
+ #[ pin]
37
+ service_fut : F ,
38
+ } ,
39
+ }
40
+
41
+ impl < AuthFut , S , F > AuthenticateFuture < AuthFut , S , F > {
42
+ fn new ( req : Request , auth_fut : AuthFut , inner : S ) -> Self {
43
+ AuthenticateFuture :: Authenticate {
44
+ req : Some ( req) ,
45
+ auth_fut,
46
+ inner,
47
+ }
48
+ }
49
+ }
50
+
51
+ impl < AuthFut , S > Future for AuthenticateFuture < AuthFut , S , S :: Future >
52
+ where
53
+ AuthFut : Future < Output = Result < Principal , ( ) > > ,
54
+ S : Service < Request , Response = Response , Error = Infallible > ,
55
+ {
56
+ type Output = Result < Response , Infallible > ;
57
+
58
+ fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
59
+ match self . as_mut ( ) . project ( ) {
60
+ AuthFutureProj :: Authenticate {
61
+ req,
62
+ auth_fut,
63
+ inner,
64
+ } => match auth_fut. poll ( cx) {
65
+ Poll :: Ready ( Ok ( principal) ) => {
66
+ let mut req = req. take ( ) . unwrap ( ) ;
67
+ req. extensions_mut ( ) . insert ( principal) ;
68
+ let service_fut = inner. call ( req) ;
69
+
70
+ self . set ( AuthenticateFuture :: ServiceCall { service_fut } ) ;
71
+ self . poll ( cx)
72
+ }
73
+ Poll :: Ready ( Err ( _) ) => Poll :: Ready ( Ok ( StatusCode :: UNAUTHORIZED . into_response ( ) ) ) ,
74
+ Poll :: Pending => Poll :: Pending ,
75
+ } ,
76
+ AuthFutureProj :: ServiceCall { service_fut } => service_fut. poll ( cx) ,
77
+ }
78
+ }
79
+ }
13
80
14
81
#[ derive( Clone ) ]
15
- pub struct AuthenticateLayer {
16
- authenticator: Authenticator ,
82
+ pub struct AuthenticateLayer < A > {
83
+ authenticator : A ,
17
84
}
18
85
19
- impl AuthenticateLayer {
20
- pub fn new(authenticator: Authenticator ) -> Self {
86
+ impl < A > AuthenticateLayer < A > {
87
+ pub fn new ( authenticator : A ) -> Self {
21
88
Self { authenticator }
22
89
}
23
90
}
24
91
25
- impl<S> Layer<S> for AuthenticateLayer {
26
- type Service = AuthenticateService<S>;
92
+ impl < S , A > Layer < S > for AuthenticateLayer < A >
93
+ where
94
+ A : Authenticate + Clone ,
95
+ {
96
+ type Service = AuthenticateService < S , A > ;
27
97
28
98
fn layer ( & self , inner : S ) -> Self :: Service {
29
99
AuthenticateService {
@@ -34,58 +104,37 @@ impl<S> Layer<S> for AuthenticateLayer {
34
104
}
35
105
36
106
#[ derive( Clone ) ]
37
- pub struct AuthenticateService<S> {
38
- authenticator: Authenticator,
107
+ pub struct AuthenticateService < S , A > {
39
108
inner : S ,
109
+ authenticator : A ,
40
110
}
41
111
42
- impl<S> Service<axum::extract:: Request> for AuthenticateService<S>
112
+ impl < S , A > Service < Request > for AuthenticateService < S , A >
43
113
where
44
- S: Service<axum::extract::Request, Response = axum::response::Response>
45
- + Send
46
- + 'static
47
- + Clone,
48
- S::Future: Send + 'static,
114
+ S : Service < Request , Response = Response , Error = Infallible > + Clone ,
115
+ A : Authenticate ,
49
116
{
50
- type Response = S::Response;
51
-
52
- type Error = S::Error;
53
-
54
- type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
55
-
56
- fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
117
+ type Response = Response ;
118
+ type Error = Infallible ;
119
+ type Future = AuthenticateFuture < A :: Output , S , S :: Future > ;
120
+
121
+ fn poll_ready (
122
+ & mut self ,
123
+ cx : & mut std:: task:: Context < ' _ > ,
124
+ ) -> std:: task:: Poll < Result < ( ) , Self :: Error > > {
57
125
self . inner . poll_ready ( cx)
58
126
}
59
127
60
- fn call(&mut self, mut request: axum::extract:: Request) -> Self::Future {
61
- let header = request
128
+ fn call ( & mut self , req : Request ) -> Self :: Future {
129
+ let token = req
62
130
. headers ( )
63
- .get(http::header::AUTHORIZATION)
64
- .and_then(|header| header.to_str().ok());
65
-
66
- let Some(token) = header else {
67
- return Box::pin(async { Ok(StatusCode::UNAUTHORIZED.into_response()) });
68
- };
69
-
70
- let Self {
71
- authenticator,
72
- mut inner,
73
- } = self.clone();
74
- let token = token.to_owned();
75
-
76
- Box::pin(async move {
77
- let principal = match authenticator.authenticate(Some(token)).await {
78
- Ok(principal) => principal,
79
- Err(_) => {
80
- tracing::warn!("Invalid token");
81
- return Ok(StatusCode::UNAUTHORIZED.into_response());
82
- }
83
- };
131
+ . get ( axum:: http:: header:: AUTHORIZATION )
132
+ . and_then ( |header| header. to_str ( ) . ok ( ) )
133
+ . map ( ToOwned :: to_owned) ;
84
134
85
- request.extensions_mut().insert(principal);
135
+ let auth_fut = self . authenticator . authenticate ( token) ;
136
+ let inner = self . inner . clone ( ) ;
86
137
87
- inner.call(request).await
88
- })
138
+ AuthenticateFuture :: new ( req, auth_fut, inner)
89
139
}
90
140
}
91
- */
0 commit comments