4
4
use crate :: controllers:: util:: RequestPartsExt ;
5
5
use crate :: headers:: { XRealIp , XRequestId } ;
6
6
use crate :: middleware:: normalize_path:: OriginalPath ;
7
+ use crate :: real_ip:: process_xff_headers;
7
8
use axum:: headers:: UserAgent ;
8
9
use axum:: middleware:: Next ;
9
10
use axum:: response:: IntoResponse ;
10
11
use axum:: { Extension , TypedHeader } ;
11
12
use http:: { Method , Request , StatusCode , Uri } ;
12
13
use parking_lot:: Mutex ;
13
14
use std:: fmt:: { self , Display , Formatter } ;
15
+ use std:: net:: IpAddr ;
14
16
use std:: ops:: Deref ;
15
17
use std:: sync:: Arc ;
16
18
use std:: time:: { Duration , Instant } ;
@@ -39,6 +41,7 @@ pub struct Metadata<'a> {
39
41
cause : Option < & ' a CauseField > ,
40
42
error : Option < & ' a ErrorField > ,
41
43
duration : Duration ,
44
+ real_ip : Option < IpAddr > ,
42
45
custom_metadata : RequestLog ,
43
46
}
44
47
@@ -71,10 +74,19 @@ impl Display for Metadata<'_> {
71
74
} ;
72
75
}
73
76
74
- match & self . request . real_ip {
75
- Some ( header) => line. add_quoted_field ( "fwd" , header. as_str ( ) ) ?,
76
- None => line. add_quoted_field ( "fwd" , "" ) ?,
77
- } ;
77
+ let real_ip = self . real_ip . map ( |ip| ip. to_string ( ) ) . unwrap_or_default ( ) ;
78
+ line. add_quoted_field ( "ip" , & real_ip) ?;
79
+
80
+ let x_real_ip = self . request . real_ip . as_ref ( ) ;
81
+ let x_real_ip = x_real_ip
82
+ . map ( |ip| ip. as_str ( ) . to_string ( ) )
83
+ . unwrap_or_default ( ) ;
84
+ line. add_quoted_field ( "fwd" , & x_real_ip) ?;
85
+
86
+ // TODO: Remove this once production traffic has shown that `ip == fwd`
87
+ if real_ip != x_real_ip {
88
+ line. add_marker ( "ip!=fwd" ) ?;
89
+ }
78
90
79
91
let response_time_in_ms = self . duration . as_millis ( ) ;
80
92
if !is_download_redirect || response_time_in_ms > 0 {
@@ -122,6 +134,8 @@ pub async fn log_requests<B>(
122
134
let custom_metadata = RequestLog :: default ( ) ;
123
135
req. extensions_mut ( ) . insert ( custom_metadata. clone ( ) ) ;
124
136
137
+ let real_ip = process_xff_headers ( req. headers ( ) ) ;
138
+
125
139
let response = next. run ( req) . await ;
126
140
127
141
let metadata = Metadata {
@@ -130,6 +144,7 @@ pub async fn log_requests<B>(
130
144
cause : response. extensions ( ) . get ( ) ,
131
145
error : response. extensions ( ) . get ( ) ,
132
146
duration : start_instant. elapsed ( ) ,
147
+ real_ip,
133
148
custom_metadata,
134
149
} ;
135
150
0 commit comments