From f2bdc85dc43e302c6dbfa28510343ba2ac2f2831 Mon Sep 17 00:00:00 2001 From: Sebastian Jeltsch Date: Sat, 17 May 2025 09:55:43 +0200 Subject: [PATCH] Parse querystrings in non-strict mode. --- Cargo.lock | 1 - trailbase-qs/Cargo.toml | 1 - trailbase-qs/src/query.rs | 21 +++++++++++++++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8bf0d6fc..029c5217 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6999,7 +6999,6 @@ name = "trailbase-qs" version = "0.1.0" dependencies = [ "base64 0.22.1", - "itertools 0.14.0", "serde", "serde-value", "serde_qs", diff --git a/trailbase-qs/Cargo.toml b/trailbase-qs/Cargo.toml index e3e38bc4..25cdc97b 100644 --- a/trailbase-qs/Cargo.toml +++ b/trailbase-qs/Cargo.toml @@ -10,7 +10,6 @@ readme = "../README.md" [dependencies] base64 = { version = "0.22.1", default-features = false, features = ["alloc"] } -itertools = "0.14.0" serde = "1.0.219" serde-value = "0.7.0" serde_qs = "0.15.0" diff --git a/trailbase-qs/src/query.rs b/trailbase-qs/src/query.rs index c8fd79a1..057e9d76 100644 --- a/trailbase-qs/src/query.rs +++ b/trailbase-qs/src/query.rs @@ -4,6 +4,8 @@ use serde::Deserialize; use crate::filter::ValueOrComposite; use crate::util::deserialize_bool; +pub type Error = serde_qs::Error; + /// TrailBase supports cursors in a few formats: /// * Integers /// * Text-encoded UUIDs ([u8; 16]) @@ -182,8 +184,9 @@ pub struct Query { } impl Query { - pub fn parse(query: &str) -> Result { - let qs = serde_qs::Config::new(5, true); + pub fn parse(query: &str) -> Result { + // NOTE: We rely on non-strict mode to parse `filter[col0]=a&b%filter[col1]=c`. + let qs = serde_qs::Config::new(5, false); return qs.deserialize_str::(query); } } @@ -201,6 +204,20 @@ mod tests { #[test] fn test_query_basic_parsing() { assert_eq!(Query::parse("").unwrap(), Query::default()); + assert_eq!(Query::parse("unknown=foo").unwrap(), Query::default()); + + assert_eq!( + Query::parse("filter%5Btext_not_null%5D=rust+client+test+0%3A+%3D%3F%261747466199") + .unwrap() + .filter + .unwrap(), + ValueOrComposite::Value(ColumnOpValue { + column: "text_not_null".to_string(), + op: CompareOp::Equal, + value: Value::String("rust client test 0: =?&1747466199".to_string()), + }) + ); + assert_eq!( Query::parse("limit=5&offset=5&count=true").unwrap(), Query {