From ca0bd76db94e5d561f5c30b7b211e865d9e9e494 Mon Sep 17 00:00:00 2001 From: tv Date: Sat, 31 Oct 2026 05:29:49 +0100 Subject: api: unify media-type stripping --- src/api/mod.rs | 6 ++++++ src/api/stats/prometheus.rs | 9 +++++---- src/api/store.rs | 12 ++++-------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/api/mod.rs b/src/api/mod.rs index 021bc52..fb860c7 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -209,3 +209,9 @@ pub(crate) fn store_status(error: StoreError, context: &str) -> ApiError { }; ApiError(status, Some(error.to_string())) } + +/// A media type without its parameters: `text/plain; charset=utf-8` is `text/plain`. +/// For `Content-Type`, and each item of an `Accept` (split at `,`). +pub(crate) fn media_type(value: &str) -> &str { + value.split(';').next().unwrap_or("").trim() +} diff --git a/src/api/stats/prometheus.rs b/src/api/stats/prometheus.rs index 0b770bd..8f7538f 100644 --- a/src/api/stats/prometheus.rs +++ b/src/api/stats/prometheus.rs @@ -5,6 +5,7 @@ use std::fmt::Write; use super::StatsResponse; +use crate::api::media_type; use crate::api::peers::{PeerListResponse, PeerLivenessStatus}; use crate::state::Incidents; use crate::transport::Destination; @@ -17,10 +18,10 @@ pub(super) const CONTENT_TYPE: &str = "text/plain; version=0.0.4; charset=utf-8" /// plain text; browsers and curl don't name either. pub(super) fn wanted(accept: Option<&str>) -> bool { accept.is_some_and(|accept| { - accept.split(',').any(|item| { - let media = item.split(';').next().unwrap_or("").trim(); - media == "application/openmetrics-text" || media == "text/plain" - }) + accept + .split(',') + .map(media_type) + .any(|media| media == "application/openmetrics-text" || media == "text/plain") }) } diff --git a/src/api/store.rs b/src/api/store.rs index c67df85..274ca70 100644 --- a/src/api/store.rs +++ b/src/api/store.rs @@ -20,7 +20,7 @@ use tokio::sync::broadcast; use tracing::{debug, error, instrument, warn}; use super::auth::AuthenticatedUser; -use super::{ApiError, store_status}; +use super::{ApiError, media_type, store_status}; use crate::document::meta; use crate::document::store::{self, StoreError, paths_related}; use crate::state::{AppState, ReadSource}; @@ -258,7 +258,7 @@ fn response_for_value( .is_some_and(|value| { value .split(',') - .any(|item| item.trim().starts_with("text/plain")) + .any(|item| media_type(item) == "text/plain") }); let (content_type, body) = if wants_text { @@ -296,12 +296,8 @@ fn body_value(headers: &HeaderMap, body: &Bytes) -> Result { serde_json::from_slice::(body).map_err(|_| StatusCode::BAD_REQUEST) } -- cgit v1.3.1