@@ -87,6 +87,12 @@ define_extractor!(
8787 client_ip:: true_client_ip
8888) ;
8989
90+ define_extractor ! (
91+ /// Extracts an IP from `X-Envoy-External-Address` (Envoy, Istio) header
92+ XEnvoyExternalAddress ,
93+ client_ip:: x_envoy_external_address
94+ ) ;
95+
9096define_extractor ! (
9197 /// Extracts an IP from `X-Real-Ip` (Nginx) header
9298 XRealIp ,
@@ -126,6 +132,8 @@ pub enum ClientIpSource {
126132 RightmostXForwardedFor ,
127133 /// IP from the `True-Client-IP` header
128134 TrueClientIp ,
135+ /// IP from the `X-Envoy-External-Address` address
136+ XEnvoyExternalAddress ,
129137 /// IP from the `X-Real-Ip` header
130138 XRealIp ,
131139}
@@ -164,6 +172,7 @@ impl FromStr for ClientIpSource {
164172 "RightmostForwarded" => Self :: RightmostForwarded ,
165173 "RightmostXForwardedFor" => Self :: RightmostXForwardedFor ,
166174 "TrueClientIp" => Self :: TrueClientIp ,
175+ "XEnvoyExternalAddress" => Self :: XEnvoyExternalAddress ,
167176 "XRealIp" => Self :: XRealIp ,
168177 _ => return Err ( ParseClientIpSourceError ( s. to_string ( ) ) ) ,
169178 } )
@@ -183,6 +192,7 @@ impl fmt::Display for ClientIpSource {
183192 ClientIpSource :: RightmostForwarded => "RightmostForwarded" ,
184193 ClientIpSource :: RightmostXForwardedFor => "RightmostXForwardedFor" ,
185194 ClientIpSource :: TrueClientIp => "TrueClientIp" ,
195+ ClientIpSource :: XEnvoyExternalAddress => "XEnvoyExternalAddress" ,
186196 ClientIpSource :: XRealIp => "XRealIp" ,
187197 } )
188198 }
@@ -219,6 +229,9 @@ where
219229 RightmostXForwardedFor :: ip_from_headers ( & parts. headers )
220230 }
221231 ClientIpSource :: TrueClientIp => TrueClientIp :: ip_from_headers ( & parts. headers ) ,
232+ ClientIpSource :: XEnvoyExternalAddress => {
233+ XEnvoyExternalAddress :: ip_from_headers ( & parts. headers )
234+ }
222235 ClientIpSource :: XRealIp => XRealIp :: ip_from_headers ( & parts. headers ) ,
223236 }
224237 . map ( Self )
@@ -289,9 +302,7 @@ mod tests {
289302
290303 #[ cfg( feature = "forwarded-header" ) ]
291304 use super :: RightmostForwarded ;
292- use super :: {
293- CfConnectingIp , ClientIpSource , FlyClientIp , RightmostXForwardedFor , TrueClientIp , XRealIp ,
294- } ;
305+ use super :: { CfConnectingIp , ClientIpSource , FlyClientIp , RightmostXForwardedFor , TrueClientIp , XEnvoyExternalAddress , XRealIp } ;
295306 use crate :: CloudFrontViewerAddress ;
296307
297308 const VALID_IPV4 : & str = "1.2.3.4" ;
@@ -489,6 +500,35 @@ mod tests {
489500 assert_eq ! ( body_to_string( resp. into_body( ) ) . await , VALID_IPV6 ) ;
490501 }
491502
503+ #[ tokio:: test]
504+ async fn x_envoy_external_address ( ) {
505+ let header = "x-envoy-external-address" ;
506+
507+ fn app ( ) -> Router {
508+ Router :: new ( ) . route ( "/" , get ( |ip : XEnvoyExternalAddress | async move { ip. 0 . to_string ( ) } ) )
509+ }
510+
511+ let req = Request :: builder ( ) . uri ( "/" ) . body ( Body :: empty ( ) ) . unwrap ( ) ;
512+ let resp = app ( ) . oneshot ( req) . await . unwrap ( ) ;
513+ assert_eq ! ( resp. status( ) , StatusCode :: INTERNAL_SERVER_ERROR ) ;
514+
515+ let req = Request :: builder ( )
516+ . uri ( "/" )
517+ . header ( header, VALID_IPV4 )
518+ . body ( Body :: empty ( ) )
519+ . unwrap ( ) ;
520+ let resp = app ( ) . oneshot ( req) . await . unwrap ( ) ;
521+ assert_eq ! ( body_to_string( resp. into_body( ) ) . await , VALID_IPV4 ) ;
522+
523+ let req = Request :: builder ( )
524+ . uri ( "/" )
525+ . header ( header, VALID_IPV6 )
526+ . body ( Body :: empty ( ) )
527+ . unwrap ( ) ;
528+ let resp = app ( ) . oneshot ( req) . await . unwrap ( ) ;
529+ assert_eq ! ( body_to_string( resp. into_body( ) ) . await , VALID_IPV6 ) ;
530+ }
531+
492532 #[ tokio:: test]
493533 async fn x_real_ip ( ) {
494534 let header = "x-real-ip" ;
@@ -539,6 +579,7 @@ mod tests {
539579 assert_match ( ClientIpSource :: RightmostForwarded ) ;
540580 assert_match ( ClientIpSource :: RightmostXForwardedFor ) ;
541581 assert_match ( ClientIpSource :: TrueClientIp ) ;
582+ assert_match ( ClientIpSource :: XEnvoyExternalAddress ) ;
542583 assert_match ( ClientIpSource :: XRealIp ) ;
543584 }
544585}
0 commit comments