Skip to content

Commit 2468b25

Browse files
authored
fix: encode every URL token in a Lucene search, not just the first (#2764)
1 parent 94d028c commit 2468b25

3 files changed

Lines changed: 35 additions & 6 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
'@hyperdx/common-utils': patch
3+
---
4+
5+
fix: Encode every `http://`, `https://` and `localhost:<port>` in a search, not
6+
just the first
7+
8+
A search naming two or more URLs left the later colons unescaped, so Lucene read
9+
them as field queries. `http://a.com http://b.com` compiled the second URL to
10+
`http ILIKE '%//b.com%'` — a predicate on a bare `http` identifier rather than a
11+
search of the log body.

‎packages/common-utils/src/__tests__/queryParser.test.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,24 @@ describe('CustomSchemaSQLSerializerV2 - json', () => {
450450
sql: "(NOT (hasToken(lower(Body), lower('red'))) AND NOT (hasToken(lower(Body), lower('blue'))))",
451451
english: 'NOT event has whole word red AND NOT event has whole word blue',
452452
},
453+
{
454+
lucene: 'http://a.com http://b.com',
455+
sql: "((hasToken(lower(Body), lower('http')) AND hasToken(lower(Body), lower('a')) AND hasToken(lower(Body), lower('com')) AND (lower(Body) LIKE lower('%http://a.com%'))) AND (hasToken(lower(Body), lower('http')) AND hasToken(lower(Body), lower('b')) AND hasToken(lower(Body), lower('com')) AND (lower(Body) LIKE lower('%http://b.com%'))))",
456+
english:
457+
'event has whole word http://a.com AND event has whole word http://b.com',
458+
},
459+
{
460+
lucene: 'https://a.com https://b.com',
461+
sql: "((hasToken(lower(Body), lower('https')) AND hasToken(lower(Body), lower('a')) AND hasToken(lower(Body), lower('com')) AND (lower(Body) LIKE lower('%https://a.com%'))) AND (hasToken(lower(Body), lower('https')) AND hasToken(lower(Body), lower('b')) AND hasToken(lower(Body), lower('com')) AND (lower(Body) LIKE lower('%https://b.com%'))))",
462+
english:
463+
'event has whole word https://a.com AND event has whole word https://b.com',
464+
},
465+
{
466+
lucene: 'localhost:3000 localhost:4000',
467+
sql: "((hasToken(lower(Body), lower('localhost')) AND hasToken(lower(Body), lower('3000')) AND (lower(Body) LIKE lower('%localhost:3000%'))) AND (hasToken(lower(Body), lower('localhost')) AND hasToken(lower(Body), lower('4000')) AND (lower(Body) LIKE lower('%localhost:4000%'))))",
468+
english:
469+
'event has whole word localhost:3000 AND event has whole word localhost:4000',
470+
},
453471
];
454472

455473
it.each(testCases)(

‎packages/common-utils/src/queryParser.ts‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,18 @@ const HAS_ALL_TOKENS_CHUNK_SIZE = 50;
3232
function encodeSpecialTokens(query: string): string {
3333
return query
3434
.replace(/\\\\/g, 'HDX_BACKSLASH_LITERAL')
35-
.replace('http://', 'http_COLON_//')
36-
.replace('https://', 'https_COLON_//')
37-
.replace(/localhost:(\d{1,5})/, 'localhost_COLON_$1')
35+
.replace(/http:\/\//g, 'http_COLON_//')
36+
.replace(/https:\/\//g, 'https_COLON_//')
37+
.replace(/localhost:(\d{1,5})/g, 'localhost_COLON_$1')
3838
.replace(/\\:/g, 'HDX_COLON');
3939
}
4040
function decodeSpecialTokens(query: string): string {
4141
return query
4242
.replace(/\\"/g, '"')
4343
.replace(/HDX_BACKSLASH_LITERAL/g, '\\')
44-
.replace('http_COLON_//', 'http://')
45-
.replace('https_COLON_//', 'https://')
46-
.replace(/localhost_COLON_(\d{1,5})/, 'localhost:$1')
44+
.replace(/http_COLON_\/\//g, 'http://')
45+
.replace(/https_COLON_\/\//g, 'https://')
46+
.replace(/localhost_COLON_(\d{1,5})/g, 'localhost:$1')
4747
.replace(/HDX_COLON/g, ':');
4848
}
4949

0 commit comments

Comments
 (0)