Skip to content

Commit bc68b1c

Browse files
authored
fix(destinations): Handle unicode characters in webhook notifications (#7586)
* fix(destinations): Handle unicode characters in webhook notifications Previously, webhook notifications would fail if they contained unicode characters in the alert data. This was because the JSON payload was not UTF-8 encoded before being sent. This commit fixes the issue by explicitly encoding the JSON data to UTF-8 and adds a test to verify the fix. * move test function to new file --------- Co-authored-by: gaojingyu <gaojingyu>
1 parent 4353a82 commit bc68b1c

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

redash/destinations/webhook.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def notify(self, alert, query, user, new_state, app, host, metadata, options):
4242
auth = HTTPBasicAuth(options.get("username"), options.get("password")) if options.get("username") else None
4343
resp = requests.post(
4444
options.get("url"),
45-
data=json_dumps(data),
45+
data=json_dumps(data).encode("utf-8"),
4646
auth=auth,
4747
headers=headers,
4848
timeout=5.0,

tests/destinations/test_webhook.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import json
2+
from unittest import mock
3+
4+
from redash.destinations.webhook import Webhook
5+
from redash.models import Alert
6+
7+
8+
def test_webhook_notify_handles_unicode():
9+
# Create a mock alert with all the properties needed by serialize_alert
10+
alert = mock.Mock()
11+
alert.id = 1
12+
alert.name = "Test Alert"
13+
alert.custom_subject = "Test Subject With Unicode: 晨"
14+
alert.custom_body = "Test Body"
15+
alert.options = {}
16+
alert.state = "ok"
17+
alert.last_triggered_at = None
18+
alert.updated_at = "2025-12-02T08:00:00Z"
19+
alert.created_at = "2025-12-02T08:00:00Z"
20+
alert.rearm = None
21+
alert.query_id = 10
22+
alert.user_id = 20
23+
24+
query = mock.Mock()
25+
user = mock.Mock()
26+
app = mock.Mock()
27+
host = "http://redash.local"
28+
options = {"url": "https://example.com/webhook", "username": "user", "password": "password"}
29+
metadata = {}
30+
new_state = Alert.TRIGGERED_STATE
31+
destination = Webhook(options)
32+
33+
with mock.patch("redash.destinations.webhook.requests.post") as mock_post:
34+
mock_response = mock.Mock()
35+
mock_response.status_code = 200
36+
mock_post.return_value = mock_response
37+
38+
destination.notify(alert, query, user, new_state, app, host, metadata, options)
39+
40+
# Get the data passed to the mock
41+
call_args, call_kwargs = mock_post.call_args
42+
sent_data = call_kwargs["data"]
43+
44+
# 1. Make sure we send bytes
45+
assert isinstance(sent_data, bytes)
46+
47+
# 2. Make sure the bytes are the correct UTF-8 encoded JSON
48+
decoded_data = json.loads(sent_data.decode("utf-8"))
49+
assert decoded_data["alert"]["title"] == alert.custom_subject
50+
assert "Test Subject With Unicode: 晨" in sent_data.decode("utf-8")

0 commit comments

Comments
 (0)