fix: allow default browser header (#25885)

Although the `format` in the request is used, the value coming
through the header is parsed earlier. So, when that lookup in
the header fails an error is returned (`InvalidMimeType`).

In this commit, there are extra checks to allow the default `Accept`
header values that come from the browser by defaulting it to `json`

closes: https://github.com/influxdata/influxdb/issues/25874
praveen/cli-jsonl-rename-format
praveen-influx 2025-01-21 13:43:07 +00:00 committed by GitHub
parent 7eb99569b5
commit 447f66d9a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 85 additions and 2 deletions

View File

@ -290,6 +290,23 @@ impl TestServer {
.await
}
pub async fn api_v3_query_sql_with_header(
&self,
params: &[(&str, &str)],
headers: HeaderMap<HeaderValue>,
) -> Response {
self.http_client
.get(format!(
"{base}/api/v3/query_sql",
base = self.client_addr()
))
.query(params)
.headers(headers)
.send()
.await
.expect("send /api/v3/query_sql request to server")
}
pub async fn api_v3_query_sql(&self, params: &[(&str, &str)]) -> Response {
self.http_client
.get(format!(

View File

@ -2,7 +2,10 @@ use core::str;
use crate::TestServer;
use futures::StreamExt;
use hyper::StatusCode;
use hyper::{
header::{HeaderValue, ACCEPT},
HeaderMap, StatusCode,
};
use influxdb3_client::Precision;
use pretty_assertions::assert_eq;
use serde::Serialize;
@ -1843,3 +1846,44 @@ async fn api_v3_query_null_tag_values_null_fields() {
resp
);
}
#[tokio::test]
async fn api_query_with_default_browser_header() {
let server = TestServer::spawn().await;
server
.write_lp_to_db(
"foo",
"cpu,region=us,host=a usage=99 2998674934",
Precision::Second,
)
.await
.unwrap();
let mut map = HeaderMap::new();
map.insert(
ACCEPT,
HeaderValue::from_static("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"),
);
let resp = server
.api_v3_query_sql_with_header(
&[
("db", "foo"),
("format", "pretty"),
("q", "SELECT * FROM cpu"),
],
map,
)
.await
.text()
.await
.unwrap();
assert_eq!(
"+------+--------+---------------------+-------+\n\
| host | region | time | usage |\n\
+------+--------+---------------------+-------+\n\
| a | us | 2065-01-08T21:15:34 | 99.0 |\n\
+------+--------+---------------------+-------+",
resp
);
}

View File

@ -1459,7 +1459,12 @@ impl QueryFormat {
Some(b"text/plain") => Ok(Self::Pretty),
Some(b"application/json" | b"*/*") | None => Ok(Self::Json),
Some(mime_type) => match String::from_utf8(mime_type.to_vec()) {
Ok(s) => Err(Error::InvalidMimeType(s)),
Ok(s) => {
if s.contains("text/html") || s.contains("*/*") {
return Ok(Self::Json);
}
Err(Error::InvalidMimeType(s))
}
Err(e) => Err(Error::NonUtf8MimeType(e)),
},
}
@ -1847,6 +1852,10 @@ fn legacy_write_error_to_response(e: WriteParseError) -> Response<Body> {
#[cfg(test)]
mod tests {
use http::{header::ACCEPT, HeaderMap, HeaderValue};
use crate::http::QueryFormat;
use super::validate_db_name;
use super::ValidateDbNameError;
@ -1857,6 +1866,19 @@ mod tests {
};
}
#[test]
fn test_try_from_headers_default_browser_accept_headers_to_json() {
let mut map = HeaderMap::new();
map.append(
ACCEPT,
HeaderValue::from_static(
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
),
);
let format = QueryFormat::try_from_headers(&map).unwrap();
assert!(matches!(format, QueryFormat::Json));
}
#[test]
fn test_validate_db_name() {
assert_validate_db_name!("foo/bar", false, Err(ValidateDbNameError::InvalidChar));