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 4a8f78b6f9 fix(alerter): keep webhook query params intact (#4249)
4a8f78b6f9 is described below
commit 4a8f78b6f973a9f09ad72a58f07a2cba41d6c97b
Author: NekoPunch <[email protected]>
AuthorDate: Sun Jul 26 02:36:47 2026 -0700
fix(alerter): keep webhook query params intact (#4249)
Co-authored-by: Tomsun28 <[email protected]>
---
.../notice/impl/WebHookAlertNotifyHandlerImpl.java | 12 +++++++-
.../impl/WebHookAlertNotifyHandlerImplTest.java | 32 ++++++++++++++++++----
2 files changed, 38 insertions(+), 6 deletions(-)
diff --git
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WebHookAlertNotifyHandlerImpl.java
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WebHookAlertNotifyHandlerImpl.java
index 8d601776f5..25f0d0e935 100644
---
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WebHookAlertNotifyHandlerImpl.java
+++
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/WebHookAlertNotifyHandlerImpl.java
@@ -17,6 +17,7 @@
package org.apache.hertzbeat.alert.notice.impl;
+import java.net.URI;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.hertzbeat.alert.notice.AlertNoticeException;
@@ -47,6 +48,15 @@ final class WebHookAlertNotifyHandlerImpl extends
AbstractAlertNotifyHandlerImpl
throw new AlertNoticeException("Webhook URL is null or empty");
}
+ // Send the URL verbatim via the URI overload: the String overload
treats it
+ // as a URI template and re-encodes it, corrupting pre-encoded
query params
+ URI hookUri;
+ try {
+ hookUri = URI.create(hookUrl);
+ } catch (IllegalArgumentException e) {
+ throw new AlertNoticeException("Invalid webhook URL: " +
e.getMessage());
+ }
+
HttpHeaders headers = new HttpHeaders();
if ("Basic".equalsIgnoreCase(receiver.getHookAuthType())) {
headers.setBasicAuth(receiver.getHookAuthToken());
@@ -59,7 +69,7 @@ final class WebHookAlertNotifyHandlerImpl extends
AbstractAlertNotifyHandlerImpl
webhookJson = webhookJson.replace(",\n }", "\n }");
HttpEntity<String> alertHttpEntity = new HttpEntity<>(webhookJson,
headers);
- ResponseEntity<String> entity =
restTemplate.postForEntity(hookUrl, alertHttpEntity, String.class);
+ ResponseEntity<String> entity =
restTemplate.postForEntity(hookUri, alertHttpEntity, String.class);
if (entity.getStatusCode().value() <
HttpStatus.BAD_REQUEST.value()) {
log.debug("Send WebHook: {} Success", hookUrl);
} else {
diff --git
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/WebHookAlertNotifyHandlerImplTest.java
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/WebHookAlertNotifyHandlerImplTest.java
index e38c389275..3d438a487f 100644
---
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/WebHookAlertNotifyHandlerImplTest.java
+++
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/WebHookAlertNotifyHandlerImplTest.java
@@ -37,11 +37,17 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.test.util.ReflectionTestUtils;
+import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
+import static
org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static
org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.net.URI;
import java.util.ResourceBundle;
/**
@@ -93,7 +99,7 @@ class WebHookAlertNotifyHandlerImplTest {
ResponseEntity<String> responseEntity =
new ResponseEntity<>("null", HttpStatus.OK);
- when(restTemplate.postForEntity(any(String.class), any(),
eq(String.class))).thenReturn(responseEntity);
+ when(restTemplate.postForEntity(any(URI.class), any(),
eq(String.class))).thenReturn(responseEntity);
webHookAlertNotifyHandler.send(receiver, template, groupAlert);
}
@@ -103,7 +109,7 @@ class WebHookAlertNotifyHandlerImplTest {
ResponseEntity<String> responseEntity =
new ResponseEntity<>("null", HttpStatus.INTERNAL_SERVER_ERROR);
- when(restTemplate.postForEntity(any(String.class), any(),
eq(String.class))).thenReturn(responseEntity);
+ when(restTemplate.postForEntity(any(URI.class), any(),
eq(String.class))).thenReturn(responseEntity);
assertThrows(AlertNoticeException.class,
@@ -117,9 +123,25 @@ class WebHookAlertNotifyHandlerImplTest {
ResponseEntity<String> responseEntity =
new ResponseEntity<>("null", HttpStatus.OK);
- when(restTemplate.postForEntity(eq(receiver.getHookUrl()), any(),
eq(String.class))).thenReturn(responseEntity);
+ when(restTemplate.postForEntity(eq(URI.create(receiver.getHookUrl())),
any(), eq(String.class))).thenReturn(responseEntity);
+
+ webHookAlertNotifyHandler.send(receiver, template, groupAlert);
+ }
+
+ @Test
+ public void testHookUrlWithPercentEncodedQuerySentVerbatim() {
+ String hookUrl =
"https://example.environment.api.powerplatform.com/workflows/wf1/triggers/manual/paths/invoke"
+ +
"?api-version=1&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=UejZsrJyaZwwAm_jArn7Ze0PIf";
+ receiver.setHookUrl(hookUrl);
+
+ RestTemplate realRestTemplate = new RestTemplate();
+ MockRestServiceServer mockServer =
MockRestServiceServer.createServer(realRestTemplate);
+ mockServer.expect(requestTo(hookUrl)).andRespond(withSuccess());
+ ReflectionTestUtils.setField(webHookAlertNotifyHandler,
"restTemplate", realRestTemplate);
webHookAlertNotifyHandler.send(receiver, template, groupAlert);
+
+ mockServer.verify();
}
@Test
@@ -145,7 +167,7 @@ class WebHookAlertNotifyHandlerImplTest {
ResponseEntity<String> responseEntity =
new ResponseEntity<>("null", HttpStatus.OK);
- when(restTemplate.postForEntity(any(String.class), any(),
eq(String.class))).thenReturn(responseEntity);
+ when(restTemplate.postForEntity(any(URI.class), any(),
eq(String.class))).thenReturn(responseEntity);
// Test various valid URLs that should work
receiver.setHookUrl("https://hooks.slack.com/services/T123/B456/complete-token");
@@ -170,7 +192,7 @@ class WebHookAlertNotifyHandlerImplTest {
ResponseEntity<String> responseEntity =
new ResponseEntity<>("null", HttpStatus.OK);
- when(restTemplate.postForEntity(eq(receiver.getHookUrl()), any(),
eq(String.class))).thenReturn(responseEntity);
+ when(restTemplate.postForEntity(eq(URI.create(receiver.getHookUrl())),
any(), eq(String.class))).thenReturn(responseEntity);
webHookAlertNotifyHandler.send(receiver, template, groupAlert);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]