diff --git a/src/servers/src/http.rs b/src/servers/src/http.rs
index 6d3ab76ec1..900ce067cb 100644
--- a/src/servers/src/http.rs
+++ b/src/servers/src/http.rs
@@ -119,6 +119,7 @@ pub mod test_helpers;
pub const HTTP_API_VERSION: &str = "v1";
pub const HTTP_API_PREFIX: &str = "/v1/";
+pub const HTTP_API_PREFIX_WITHOUT_TRAILING_SLASH: &str = "/v1";
/// Default http body limit (64M).
const DEFAULT_BODY_LIMIT: ReadableSize = ReadableSize::mb(64);
diff --git a/src/servers/src/http/client_ip.rs b/src/servers/src/http/client_ip.rs
index 70df554ebb..07379cba3c 100644
--- a/src/servers/src/http/client_ip.rs
+++ b/src/servers/src/http/client_ip.rs
@@ -25,16 +25,19 @@ use common_telemetry::warn;
///
/// Extracts client address from [`ConnectInfo`] if available.
pub async fn log_error_with_client_ip(req: Request
, next: Next) -> Response {
- let request_info = req
- .extensions()
- .get::>()
- .map(|c| c.0)
- .map(|addr| {
- let method = req.method().clone();
- let uri = req.uri().clone();
- let matched_path = req.extensions().get::().cloned();
- (addr, method, uri, matched_path)
- });
+ let request_info = if is_public_http_api_path(req.uri().path()) {
+ req.extensions()
+ .get::>()
+ .map(|c| c.0)
+ .map(|addr| {
+ let method = req.method().clone();
+ let uri = req.uri().clone();
+ let matched_path = req.extensions().get::().cloned();
+ (addr, method, uri, matched_path)
+ })
+ } else {
+ None
+ };
let response = next.run(req).await;
@@ -57,6 +60,11 @@ pub async fn log_error_with_client_ip(req: Request, next: Next) -> Respons
response
}
+fn is_public_http_api_path(path: &str) -> bool {
+ path == super::HTTP_API_PREFIX_WITHOUT_TRAILING_SLASH
+ || path.starts_with(super::HTTP_API_PREFIX)
+}
+
#[cfg(test)]
mod tests {
use axum::Router;
@@ -66,6 +74,19 @@ mod tests {
use super::*;
+ #[test]
+ fn test_public_http_api_path_matches_v1_prefix() {
+ assert!(is_public_http_api_path("/v1"));
+ assert!(is_public_http_api_path("/v1/sql"));
+ assert!(is_public_http_api_path("/v1/prometheus/api/v1/query"));
+
+ assert!(!is_public_http_api_path("/"));
+ assert!(!is_public_http_api_path("/health"));
+ assert!(!is_public_http_api_path("/status"));
+ assert!(!is_public_http_api_path("/metrics"));
+ assert!(!is_public_http_api_path("/v10/sql"));
+ }
+
#[tokio::test]
async fn test_middleware_passes_error_response() {
async fn not_found_handler() -> StatusCode {