This is an automated email from the ASF dual-hosted git repository.
tomsun28 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/master by this push:
new 0a38a73756 [improve] form-urlencode SQL request body in
GreptimeSqlQueryExecutor (#4223)
0a38a73756 is described below
commit 0a38a7375621220d2f9dec9b713f9edebd6ac4df
Author: Duansg <[email protected]>
AuthorDate: Tue Jul 21 23:19:43 2026 +0800
[improve] form-urlencode SQL request body in GreptimeSqlQueryExecutor
(#4223)
Co-authored-by: Tomsun28 <[email protected]>
---
.../warehouse/db/GreptimeSqlQueryExecutor.java | 4 ++-
.../warehouse/db/GreptimeSqlQueryExecutorTest.java | 36 ++++++++++++++++++++++
2 files changed, 39 insertions(+), 1 deletion(-)
diff --git
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/GreptimeSqlQueryExecutor.java
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/GreptimeSqlQueryExecutor.java
index 0afcc8fe20..bfac687599 100644
---
a/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/GreptimeSqlQueryExecutor.java
+++
b/hertzbeat-warehouse/src/main/java/org/apache/hertzbeat/warehouse/db/GreptimeSqlQueryExecutor.java
@@ -38,6 +38,8 @@ import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -79,7 +81,7 @@ public class GreptimeSqlQueryExecutor extends
SqlQueryExecutor {
headers.add(HttpHeaders.AUTHORIZATION, NetworkConstants.BASIC +
SignConstants.BLANK + encodedAuth);
}
- String requestBody = "sql=" + queryString;
+ String requestBody = "sql=" + URLEncoder.encode(queryString,
StandardCharsets.UTF_8);
HttpEntity<String> httpEntity = new HttpEntity<>(requestBody, headers);
String url = greptimeProperties.httpEndpoint() + QUERY_PATH;
diff --git
a/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/db/GreptimeSqlQueryExecutorTest.java
b/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/db/GreptimeSqlQueryExecutorTest.java
index 1445ed5f0c..ea927bd403 100644
---
a/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/db/GreptimeSqlQueryExecutorTest.java
+++
b/hertzbeat-warehouse/src/test/java/org/apache/hertzbeat/warehouse/db/GreptimeSqlQueryExecutorTest.java
@@ -20,12 +20,16 @@
package org.apache.hertzbeat.warehouse.db;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -34,6 +38,7 @@ import
org.apache.hertzbeat.warehouse.store.history.tsdb.greptime.GreptimeSqlQue
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpEntity;
@@ -90,6 +95,37 @@ class GreptimeSqlQueryExecutorTest {
assertEquals(85.5, result.get(0).get("value"));
}
+ @Test
+ @SuppressWarnings("unchecked")
+ void testRequestBodyIsFormEncoded() {
+ when(restTemplate.exchange(
+ any(String.class),
+ eq(HttpMethod.POST),
+ any(HttpEntity.class),
+ eq(GreptimeSqlQueryContent.class)
+ )).thenReturn(new ResponseEntity<>(new GreptimeSqlQueryContent(),
HttpStatus.OK));
+
+ // SQL carrying form-urlencoded metacharacters that would pollute the
request body
+ // if concatenated raw: '&' would start a second sql= parameter and
override the query.
+ String sql = "SELECT * FROM t WHERE name = 'x&sql=DROP TABLE t'";
+ greptimeSqlQueryExecutor.execute(sql);
+
+ ArgumentCaptor<HttpEntity<String>> captor =
ArgumentCaptor.forClass(HttpEntity.class);
+ verify(restTemplate).exchange(
+ any(String.class),
+ eq(HttpMethod.POST),
+ captor.capture(),
+ eq(GreptimeSqlQueryContent.class));
+
+ String body = captor.getValue().getBody();
+ assertNotNull(body);
+ // The body must be a single sql= parameter; the '&' inside the SQL
must be encoded.
+ String encodedValue = body.substring("sql=".length());
+ assertFalse(encodedValue.contains("&"), "raw '&' in body causes HTTP
parameter pollution");
+ // Decoding the value must yield exactly the original SQL, lossless
round-trip.
+ assertEquals(sql, URLDecoder.decode(encodedValue,
StandardCharsets.UTF_8));
+ }
+
@Test
void testExecuteError() {
// Mock error response
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]