[Add] Ip tracking
All checks were successful
CI / checks (push) Successful in 5m27s

This commit is contained in:
Alex Emmet 2026-07-20 01:39:27 +02:00
commit 04760fd88d
15 changed files with 136 additions and 20 deletions

View file

@ -312,6 +312,7 @@ mod tests {
uri: Uri::from_static("/health"),
headers: Default::default(),
body: Some(Bytes::new()),
remote_addr: "127.0.0.1:4433".parse().unwrap(),
};
let response =
router.handler(&Method::GET, "/health").unwrap()(request, Http3Response::default())
@ -339,6 +340,7 @@ mod tests {
uri: Uri::from_static("/api/get/user%2D123/profile.json"),
headers: Default::default(),
body: Some(Bytes::new()),
remote_addr: "127.0.0.1:4433".parse().unwrap(),
};
let response = handler(request, Http3Response::default(), params).await;
assert_eq!(response.body, vec![Bytes::from("user-123")]);
@ -383,6 +385,7 @@ mod tests {
uri: Uri::from_static("/api/users/profile.json"),
headers: Default::default(),
body: None,
remote_addr: "127.0.0.1:4433".parse().unwrap(),
};
let response = handler(request, Http3Response::default(), params).await;
assert_eq!(response.status, StatusCode::CREATED);

View file

@ -353,6 +353,7 @@ async fn run_driver(
if let Some(ref m) = metrics {
m.connection_accepted();
}
let remote_addr = connection.remote_address();
let mut tasks = tokio::task::JoinSet::new();
loop {
@ -407,6 +408,7 @@ async fn run_driver(
max_request_body,
request_timeout,
metrics.clone(),
remote_addr,
));
let result =
accept_web_connection(session, mtp_path, connection, send_pongs, policy, host_config.clone())
@ -440,7 +442,7 @@ async fn run_driver(
let req_start = std::time::Instant::now();
let (response, status) = match tokio::time::timeout(
request_timeout,
handle_http_request(request, &mut stream, &router, max_request_body),
handle_http_request(request, &mut stream, &router, max_request_body, remote_addr),
)
.await
{
@ -499,11 +501,12 @@ async fn handle_http_request<S>(
stream: &mut h3::server::RequestStream<S, Bytes>,
router: &Router,
max_request_body: usize,
remote_addr: SocketAddr,
) -> Result<(Http3Response, StatusCode), WebServerError>
where
S: h3::quic::BidiStream<Bytes>,
{
let (request, too_large) = read_request(request, stream, max_request_body)
let (request, too_large) = read_request(request, stream, max_request_body, remote_addr)
.await
.map_err(|e| WebServerError::Http(format!("request body read failed: {e}")))?;
if too_large {
@ -546,6 +549,7 @@ async fn run_session_requests(
max_request_body: usize,
request_timeout: Duration,
metrics: Option<Arc<dyn WebServerMetrics>>,
remote_addr: SocketAddr,
) {
loop {
match session.accept_bi().await {
@ -560,7 +564,13 @@ async fn run_session_requests(
let req_start = std::time::Instant::now();
let (response, status) = match tokio::time::timeout(
request_timeout,
handle_http_request(request, &mut stream, &router, max_request_body),
handle_http_request(
request,
&mut stream,
&router,
max_request_body,
remote_addr,
),
)
.await
{
@ -590,6 +600,7 @@ async fn read_request<S>(
request: Request<()>,
stream: &mut h3::server::RequestStream<S, Bytes>,
max_body: usize,
remote_addr: SocketAddr,
) -> Result<(Http3Request, bool), h3::error::StreamError>
where
S: h3::quic::BidiStream<Bytes>,
@ -610,6 +621,7 @@ where
uri: parts.uri,
headers: parts.headers,
body: (!body.is_empty()).then(|| Bytes::from(body)),
remote_addr,
},
too_large,
))

View file

@ -1,5 +1,6 @@
use bytes::Bytes;
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, Uri};
use std::net::SocketAddr;
use tokio::sync::mpsc;
/// An owned HTTP/3 request passed to a route handler.
@ -9,6 +10,7 @@ pub struct Http3Request {
pub uri: Uri,
pub headers: HeaderMap,
pub body: Option<Bytes>,
pub remote_addr: SocketAddr,
}
/// A buffered HTTP/3 response returned from a route handler.

View file

@ -43,6 +43,10 @@ impl H3TransportConnection {
pub(crate) fn new(session: Arc<Session>, quinn: quinn::Connection) -> Self {
Self { session, quinn }
}
pub(crate) fn remote_addr(&self) -> std::net::SocketAddr {
self.quinn.remote_address()
}
}
#[async_trait::async_trait]
@ -255,6 +259,7 @@ async fn accept_web_connection_inner(
let auth_handshake_started = Instant::now();
let max_message_size = policy.max_message_size;
let transport = H3TransportConnection::new(session, quinn);
let remote_addr = transport.remote_addr();
let policy = Arc::new(policy);
let receiver = WebMtpReceiver::new(transport.clone(), policy.clone());
@ -277,14 +282,16 @@ async fn accept_web_connection_inner(
if send_pongs {
receiver.respond_to_pings(sender.clone()).await;
}
let connection: WebMTPConnection = mtp_host::MTPConnection::from_transport_parts(
negotiated,
codec,
sender,
receiver,
path,
description.clone(),
);
let connection: WebMTPConnection =
mtp_host::MTPConnection::from_transport_parts_with_remote_addr(
negotiated,
codec,
sender,
receiver,
path,
description.clone(),
Some(remote_addr),
);
#[cfg(feature = "crypto")]
let mut connection = connection;
#[cfg(feature = "crypto")]