From 16f15d4ea1de866bf53812e03f3438277e2d47c8 Mon Sep 17 00:00:00 2001
From: discord9 <55937128+discord9@users.noreply.github.com>
Date: Thu, 15 Oct 2026 14:57:48 +0800
Subject: [PATCH] fix: reject invalid HTTP read hints and report actual
parallelism bounds
Return InvalidParameter for an invalid applied generic read_preference while preserving dedicated-header precedence. Format the query.parallelism diagnostic from the supplied maximum so wire errors do not incorrectly report the public cap.
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
---
src/servers/src/http/hints.rs | 23 ++++++++++++++++-------
src/session/src/query_options.rs | 2 +-
2 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/src/servers/src/http/hints.rs b/src/servers/src/http/hints.rs
index 9d5ca035d0c..722ac66534c 100644
--- a/src/servers/src/http/hints.rs
+++ b/src/servers/src/http/hints.rs
@@ -20,6 +20,7 @@ use common_telemetry::debug;
use session::context::QueryContext;
use session::hints::is_reserved_extension_key;
+use crate::error::{InvalidParameterSnafu, Result};
use crate::hint_headers;
pub async fn extract_hints(mut request: Request
, next: Next) -> Response {
@@ -31,8 +32,10 @@ pub async fn extract_hints(mut request: Request, next: Next) -> Response {
Ok(hints) => hints,
Err(error) => return error.into_response(),
};
- if let Some(query_ctx) = request.extensions_mut().get_mut::() {
- apply_hints(query_ctx, hints, dedicated_read_preference);
+ if let Some(query_ctx) = request.extensions_mut().get_mut::()
+ && let Err(error) = apply_hints(query_ctx, hints, dedicated_read_preference)
+ {
+ return error.into_response();
}
next.run(request).await
}
@@ -41,7 +44,7 @@ fn apply_hints(
query_ctx: &mut QueryContext,
hints: Vec<(String, String)>,
dedicated_read_preference: bool,
-) {
+) -> Result<()> {
for (key, value) in hints {
if is_reserved_extension_key(&key) {
debug!(
@@ -51,15 +54,20 @@ fn apply_hints(
continue;
}
if key.eq_ignore_ascii_case(session::hints::READ_PREFERENCE_HINT) {
- if !dedicated_read_preference
- && let Ok(preference) = value.parse::()
- {
+ if !dedicated_read_preference {
+ let preference = value.parse::().map_err(|_| {
+ InvalidParameterSnafu {
+ reason: format!("Invalid read_preference hint: {value}"),
+ }
+ .build()
+ })?;
query_ctx.set_read_preference(preference);
}
} else {
query_ctx.set_extension(key, value);
}
}
+ Ok(())
}
#[cfg(test)]
@@ -106,7 +114,8 @@ mod tests {
("ttl".to_string(), "7d".to_string()),
],
false,
- );
+ )
+ .unwrap();
assert_eq!(
query_ctx.remote_query_id(),
diff --git a/src/session/src/query_options.rs b/src/session/src/query_options.rs
index 521123718c2..dca6456b0be 100644
--- a/src/session/src/query_options.rs
+++ b/src/session/src/query_options.rs
@@ -60,7 +60,7 @@ pub fn parse_query_option(
return InvalidConfigValueSnafu {
name: key,
value,
- hint: "query.parallelism must be between 1 and 1024",
+ hint: format!("query.parallelism must be between 1 and {max_parallelism}"),
}
.fail();
}