Skip to content

Commit d5f4c7e

Browse files
committed
fix: case sensitive tag filtering for A|B tags in /messages/tags query
1 parent 6540448 commit d5f4c7e

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

crates/server/src/indexer.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,17 @@ impl AtlasIndexerClient {
330330
pub async fn mainnet_messages_by_tag(
331331
&self,
332332
protocol: Option<&str>,
333-
tag_key: &str,
333+
tag_keys: &[String],
334334
tag_value: &str,
335335
limit: u64,
336336
) -> Result<Vec<MainnetMessage>, Error> {
337+
if tag_keys.is_empty() {
338+
return Ok(Vec::new());
339+
}
340+
let placeholders = std::iter::repeat("?")
341+
.take(tag_keys.len())
342+
.collect::<Vec<_>>()
343+
.join(", ");
337344
let protocol_clause = if protocol.is_some() {
338345
" and m.protocol = ?"
339346
} else {
@@ -349,17 +356,17 @@ impl AtlasIndexerClient {
349356
on filter.protocol = m.protocol and filter.block_height = m.block_height and filter.msg_id = m.msg_id \
350357
left join ao_mainnet_message_tags t \
351358
on t.protocol = m.protocol and t.block_height = m.block_height and t.msg_id = m.msg_id \
352-
where filter.tag_key = ? and filter.tag_value = ?{} \
359+
where filter.tag_key in ({}) and filter.tag_value = ?{} \
353360
group by m.protocol, m.block_height, m.block_timestamp, m.msg_id, m.owner, m.recipient, m.bundled_in, m.data_size, m.ts \
354361
order by m.block_height desc, m.msg_id desc \
355362
limit ?",
356-
protocol_clause
363+
placeholders, protocol_clause
357364
);
358-
let mut query = self
359-
.client
360-
.query(&sql)
361-
.bind(tag_key)
362-
.bind(tag_value);
365+
let mut query = self.client.query(&sql);
366+
for key in tag_keys {
367+
query = query.bind(key);
368+
}
369+
query = query.bind(tag_value);
363370
if let Some(p) = protocol {
364371
query = query.bind(p);
365372
}

crates/server/src/routes.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,12 @@ pub async fn get_mainnet_messages_by_tag(
234234
.filter(|v| !v.is_empty())
235235
.ok_or_else(|| ServerError::from(anyhow!("missing tag value")))?;
236236
let client = AtlasIndexerClient::new().await?;
237+
let tag_keys = build_tag_key_variants(protocol.as_deref(), &key);
238+
if tag_keys.is_empty() {
239+
return Err(ServerError::from(anyhow!("invalid tag key")));
240+
}
237241
let rows = client
238-
.mainnet_messages_by_tag(protocol.as_deref(), &key, &value, limit)
242+
.mainnet_messages_by_tag(protocol.as_deref(), &tag_keys, &value, limit)
239243
.await?;
240244
Ok(Json(serde_json::to_value(&rows)?))
241245
}
@@ -259,3 +263,40 @@ fn parse_protocol(value: Option<&String>) -> Result<Option<String>, ServerError>
259263
}
260264
Ok(None)
261265
}
266+
267+
fn build_tag_key_variants(protocol: Option<&str>, key: &str) -> Vec<String> {
268+
let trimmed = key.trim();
269+
if trimmed.is_empty() {
270+
return Vec::new();
271+
}
272+
let lower = trimmed.to_ascii_lowercase();
273+
let header = to_header_case(trimmed);
274+
match protocol {
275+
Some("A") => vec![lower],
276+
Some("B") => vec![header],
277+
_ => {
278+
if lower == header {
279+
vec![lower]
280+
} else {
281+
vec![lower, header]
282+
}
283+
}
284+
}
285+
}
286+
287+
fn to_header_case(input: &str) -> String {
288+
let mut result = String::with_capacity(input.len());
289+
for (i, segment) in input.split('-').enumerate() {
290+
if i > 0 {
291+
result.push('-');
292+
}
293+
let mut chars = segment.chars();
294+
if let Some(first) = chars.next() {
295+
result.push(first.to_ascii_uppercase());
296+
}
297+
for c in chars {
298+
result.push(c.to_ascii_lowercase());
299+
}
300+
}
301+
result
302+
}

0 commit comments

Comments
 (0)