From e8d5228250580a651a955ca97dce54b610ee2683 Mon Sep 17 00:00:00 2001 From: ManyTheFish Date: Thu, 9 Oct 2025 16:57:48 +0200 Subject: [PATCH] factorize metadata header --- crates/meilisearch/src/routes/indexes/search.rs | 16 +++------------- crates/meilisearch/src/routes/mod.rs | 13 +++++++++++++ crates/meilisearch/src/routes/multi_search.rs | 17 ++++------------- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/crates/meilisearch/src/routes/indexes/search.rs b/crates/meilisearch/src/routes/indexes/search.rs index 91fef74fc..8012f2302 100644 --- a/crates/meilisearch/src/routes/indexes/search.rs +++ b/crates/meilisearch/src/routes/indexes/search.rs @@ -22,12 +22,12 @@ use crate::extractors::authentication::GuardedData; use crate::extractors::sequential_extractor::SeqHandler; use crate::metrics::MEILISEARCH_DEGRADED_SEARCH_REQUESTS; use crate::routes::indexes::search_analytics::{SearchAggregator, SearchGET, SearchPOST}; +use crate::routes::parse_include_metadata_header; use crate::search::{ add_search_rules, perform_search, HybridQuery, MatchingStrategy, RankingScoreThreshold, RetrieveVectors, SearchKind, SearchParams, SearchQuery, SearchResult, SemanticRatio, DEFAULT_CROP_LENGTH, DEFAULT_CROP_MARKER, DEFAULT_HIGHLIGHT_POST_TAG, DEFAULT_HIGHLIGHT_PRE_TAG, DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_OFFSET, DEFAULT_SEMANTIC_RATIO, - INCLUDE_METADATA_HEADER, }; use crate::search_queue::SearchQueue; @@ -346,12 +346,7 @@ pub async fn search_with_url_query( search_kind(&query, index_scheduler.get_ref(), index_uid.to_string(), &index)?; let retrieve_vector = RetrieveVectors::new(query.retrieve_vectors); let permit = search_queue.try_get_search_permit().await?; - let include_metadata = req - .headers() - .get(INCLUDE_METADATA_HEADER) - .and_then(|h| h.to_str().ok()) - .map(|v| matches!(v.to_lowercase().as_str(), "true" | "1")) - .unwrap_or(false); + let include_metadata = parse_include_metadata_header(&req); let search_result = tokio::task::spawn_blocking(move || { perform_search( @@ -464,12 +459,7 @@ pub async fn search_with_post( search_kind(&query, index_scheduler.get_ref(), index_uid.to_string(), &index)?; let retrieve_vectors = RetrieveVectors::new(query.retrieve_vectors); - let include_metadata = req - .headers() - .get(INCLUDE_METADATA_HEADER) - .and_then(|h| h.to_str().ok()) - .map(|v| matches!(v.to_lowercase().as_str(), "true" | "1")) - .unwrap_or(false); + let include_metadata = parse_include_metadata_header(&req); let permit = search_queue.try_get_search_permit().await?; let search_result = tokio::task::spawn_blocking(move || { diff --git a/crates/meilisearch/src/routes/mod.rs b/crates/meilisearch/src/routes/mod.rs index 5a6780cbb..74b3215ac 100644 --- a/crates/meilisearch/src/routes/mod.rs +++ b/crates/meilisearch/src/routes/mod.rs @@ -42,6 +42,7 @@ use crate::routes::multi_search::SearchResults; use crate::routes::network::{Network, Remote}; use crate::routes::swap_indexes::SwapIndexesPayload; use crate::routes::webhooks::{WebhookResults, WebhookSettings, WebhookWithMetadata}; +use crate::search::INCLUDE_METADATA_HEADER; use crate::search::{ FederatedSearch, FederatedSearchResult, Federation, FederationOptions, MergeFacets, SearchQueryWithIndex, SearchResultWithIndex, SimilarQuery, SimilarResult, @@ -184,6 +185,18 @@ pub fn is_dry_run(req: &HttpRequest, opt: &Opt) -> Result { .is_some_and(|s| s.to_lowercase() == "true")) } +/// Parse the `Meili-Include-Metadata` header from an HTTP request. +/// +/// Returns `true` if the header is present and set to "true" or "1" (case-insensitive). +/// Returns `false` if the header is not present or has any other value. +pub fn parse_include_metadata_header(req: &HttpRequest) -> bool { + req.headers() + .get(INCLUDE_METADATA_HEADER) + .and_then(|h| h.to_str().ok()) + .map(|v| matches!(v.to_lowercase().as_str(), "true" | "1")) + .unwrap_or(false) +} + #[derive(Debug, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct SummarizedTaskView { diff --git a/crates/meilisearch/src/routes/multi_search.rs b/crates/meilisearch/src/routes/multi_search.rs index 30938298d..50e00fef1 100644 --- a/crates/meilisearch/src/routes/multi_search.rs +++ b/crates/meilisearch/src/routes/multi_search.rs @@ -21,9 +21,10 @@ use crate::routes::indexes::search::search_kind; use crate::search::{ add_search_rules, perform_federated_search, perform_search, FederatedSearch, FederatedSearchResult, RetrieveVectors, SearchParams, SearchQueryWithIndex, - SearchResultWithIndex, INCLUDE_METADATA_HEADER, PROXY_SEARCH_HEADER, PROXY_SEARCH_HEADER_VALUE, + SearchResultWithIndex, PROXY_SEARCH_HEADER, PROXY_SEARCH_HEADER_VALUE, }; use crate::search_queue::SearchQueue; +use crate::routes::parse_include_metadata_header; #[derive(OpenApi)] #[openapi( @@ -202,12 +203,7 @@ pub async fn multi_search_with_post( .headers() .get(PROXY_SEARCH_HEADER) .is_some_and(|value| value.as_bytes() == PROXY_SEARCH_HEADER_VALUE.as_bytes()); - let include_metadata = req - .headers() - .get(INCLUDE_METADATA_HEADER) - .and_then(|h| h.to_str().ok()) - .map(|v| matches!(v.to_lowercase().as_str(), "true" | "1")) - .unwrap_or(false); + let include_metadata = parse_include_metadata_header(&req); let search_result = perform_federated_search( &index_scheduler, queries, @@ -235,12 +231,7 @@ pub async fn multi_search_with_post( HttpResponse::Ok().json(search_result?) } None => { - let include_metadata = req - .headers() - .get(INCLUDE_METADATA_HEADER) - .and_then(|h| h.to_str().ok()) - .map(|v| matches!(v.to_lowercase().as_str(), "true" | "1")) - .unwrap_or(false); + let include_metadata = parse_include_metadata_header(&req); // Explicitly expect a `(ResponseError, usize)` for the error type rather than `ResponseError` only, // so that `?` doesn't work if it doesn't use `with_index`, ensuring that it is not forgotten in case of code