1
1
//! HTTP server routes for version `v1`.
2
+ use std:: net:: SocketAddr ;
2
3
use std:: sync:: Arc ;
4
+ use std:: time:: Duration ;
3
5
6
+ use axum:: http:: { HeaderName , HeaderValue } ;
7
+ use axum:: response:: Response ;
4
8
use axum:: routing:: get;
5
9
use axum:: Router ;
6
10
use axum_client_ip:: SecureClientIpSource ;
11
+ use hyper:: Request ;
7
12
use tower_http:: compression:: CompressionLayer ;
13
+ use tower_http:: propagate_header:: PropagateHeaderLayer ;
14
+ use tower_http:: request_id:: { MakeRequestId , RequestId , SetRequestIdLayer } ;
15
+ use tower_http:: trace:: { DefaultMakeSpan , TraceLayer } ;
16
+ use tracing:: { Level , Span } ;
17
+ use uuid:: Uuid ;
8
18
9
19
use super :: handlers:: { announce, health_check, scrape} ;
10
20
use crate :: core:: Tracker ;
@@ -14,7 +24,7 @@ use crate::core::Tracker;
14
24
/// > **NOTICE**: it's added a layer to get the client IP from the connection
15
25
/// info. The tracker could use the connection info to get the client IP.
16
26
#[ allow( clippy:: needless_pass_by_value) ]
17
- pub fn router ( tracker : Arc < Tracker > ) -> Router {
27
+ pub fn router ( tracker : Arc < Tracker > , server_socket_addr : SocketAddr ) -> Router {
18
28
Router :: new ( )
19
29
// Health check
20
30
. route ( "/health_check" , get ( health_check:: handler) )
@@ -27,4 +37,47 @@ pub fn router(tracker: Arc<Tracker>) -> Router {
27
37
// Add extension to get the client IP from the connection info
28
38
. layer ( SecureClientIpSource :: ConnectInfo . into_extension ( ) )
29
39
. layer ( CompressionLayer :: new ( ) )
40
+ . layer ( SetRequestIdLayer :: x_request_id ( RequestIdGenerator ) )
41
+ . layer ( PropagateHeaderLayer :: new ( HeaderName :: from_static ( "x-request-id" ) ) )
42
+ . layer (
43
+ TraceLayer :: new_for_http ( )
44
+ . make_span_with ( DefaultMakeSpan :: new ( ) . level ( Level :: INFO ) )
45
+ . on_request ( move |request : & Request < axum:: body:: Body > , _span : & Span | {
46
+ let method = request. method ( ) . to_string ( ) ;
47
+ let uri = request. uri ( ) . to_string ( ) ;
48
+ let request_id = request
49
+ . headers ( )
50
+ . get ( "x-request-id" )
51
+ . map ( |v| v. to_str ( ) . unwrap_or_default ( ) )
52
+ . unwrap_or_default ( ) ;
53
+
54
+ tracing:: span!(
55
+ target: "HTTP TRACKER" ,
56
+ tracing:: Level :: INFO , "request" , server_socket_addr= %server_socket_addr, method = %method, uri = %uri, request_id = %request_id) ;
57
+ } )
58
+ . on_response ( move |response : & Response , latency : Duration , _span : & Span | {
59
+ let status_code = response. status ( ) ;
60
+ let request_id = response
61
+ . headers ( )
62
+ . get ( "x-request-id" )
63
+ . map ( |v| v. to_str ( ) . unwrap_or_default ( ) )
64
+ . unwrap_or_default ( ) ;
65
+ let latency_ms = latency. as_millis ( ) ;
66
+
67
+ tracing:: span!(
68
+ target: "HTTP TRACKER" ,
69
+ tracing:: Level :: INFO , "response" , server_socket_addr= %server_socket_addr, latency = %latency_ms, status = %status_code, request_id = %request_id) ;
70
+ } ) ,
71
+ )
72
+ . layer ( SetRequestIdLayer :: x_request_id ( RequestIdGenerator ) )
73
+ }
74
+
75
+ #[ derive( Clone , Default ) ]
76
+ struct RequestIdGenerator ;
77
+
78
+ impl MakeRequestId for RequestIdGenerator {
79
+ fn make_request_id < B > ( & mut self , _request : & Request < B > ) -> Option < RequestId > {
80
+ let id = HeaderValue :: from_str ( & Uuid :: new_v4 ( ) . to_string ( ) ) . expect ( "UUID is a valid HTTP header value" ) ;
81
+ Some ( RequestId :: new ( id) )
82
+ }
30
83
}
0 commit comments