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]

Reply via email to