1+ use std:: {
2+ future:: { ready, Ready } ,
3+ rc:: Rc
4+ } ;
5+
6+ use actix_web:: {
7+ dev:: { self , Service , ServiceRequest , ServiceResponse , Transform } ,
8+ Error ,
9+ http:: { header, StatusCode } , HttpResponseBuilder
10+ } ;
11+ use futures_util:: future:: LocalBoxFuture ;
12+
13+
14+ // You can move this struct to a separate file.
15+ // this struct below just for example.
16+ use serde:: { Deserialize , Serialize } ;
17+
18+ #[ derive( Debug , Serialize , Deserialize ) ]
19+ pub struct HttpData {
20+ pub data : String ,
21+ }
22+ // this implementation is optional
23+ impl Default for HttpData {
24+ fn default ( ) -> Self {
25+ Self {
26+ data : "Hello this is default error message! you need to set Authorization header to get thru this." . to_string ( ) ,
27+ }
28+ }
29+ }
30+
31+
32+ pub struct ReturnHttpResponse ;
33+
34+ impl < S : ' static > Transform < S , ServiceRequest > for ReturnHttpResponse
35+ where
36+ S : Service < ServiceRequest , Response = ServiceResponse , Error = Error > ,
37+ S :: Future : ' static
38+ {
39+ type Response = ServiceResponse ;
40+ type Error = Error ;
41+ type InitError = ( ) ;
42+ type Transform = AuthMiddleware < S > ;
43+ type Future = Ready < Result < Self :: Transform , Self :: InitError > > ;
44+
45+ fn new_transform ( & self , service : S ) -> Self :: Future {
46+ ready ( Ok ( AuthMiddleware {
47+ service : Rc :: new ( service) ,
48+ } ) )
49+ }
50+ }
51+
52+ pub struct AuthMiddleware < S > {
53+ // This is special: We need this to avoid lifetime issues.
54+ service : Rc < S > ,
55+ }
56+
57+ impl < S > Service < ServiceRequest > for AuthMiddleware < S >
58+ where
59+ S : Service < ServiceRequest , Response = ServiceResponse , Error = Error > + ' static ,
60+ S :: Future : ' static
61+ {
62+ type Response = ServiceResponse ;
63+ type Error = Error ;
64+ type Future = LocalBoxFuture < ' static , Result < Self :: Response , Self :: Error > > ;
65+
66+ dev:: forward_ready!( service) ;
67+
68+ fn call ( & self , req : ServiceRequest ) -> Self :: Future {
69+ let svc = self . service . clone ( ) ;
70+
71+ Box :: pin ( async move {
72+
73+ let headers = req. headers ( ) ;
74+ let _ = match headers. get ( "Authorization" ) {
75+ Some ( e) => e,
76+ None => {
77+ let new_response = HttpResponseBuilder :: new ( StatusCode :: BAD_REQUEST )
78+ . insert_header ( ( header:: CONTENT_TYPE , "application/json" ) )
79+ . json ( HttpData :: default ( ) ) ;
80+ return Ok ( ServiceResponse :: new (
81+ req. request ( ) . to_owned ( ) , /* or req.request().clone() */
82+ new_response
83+ ) )
84+ }
85+ } ;
86+
87+ let res = svc. call ( req) . await ?;
88+ Ok ( res)
89+ } )
90+ }
91+ }
0 commit comments