fix: handle ntfy webhook headers dynamically to prevent template syntax errors

- ntfy template headers contained Go template syntax that wasn't being processed
- Added special handling for ntfy webhooks to set Title, Priority, and Tags dynamically
- Headers are now set based on actual alert level and details
- Ignores template-syntax headers from webhook config to prevent errors
- Fixes issue where ntfy webhooks with preset headers would fail to send
This commit is contained in:
Pulse Monitor 2025-09-04 18:14:29 +00:00
parent 5681a0fbd5
commit 3d941b40cc
2 changed files with 57 additions and 4 deletions

View file

@ -625,8 +625,62 @@ func (n *NotificationManager) sendWebhookRequest(webhook WebhookConfig, jsonData
// Set headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "Pulse-Monitoring/2.0")
// Special handling for ntfy service - add dynamic headers based on alert level
if webhook.Service == "ntfy" {
// Set Content-Type for ntfy (plain text)
req.Header.Set("Content-Type", "text/plain")
// Set dynamic headers based on alert level
title := fmt.Sprintf("%s: %s",
func() string {
switch alert.Level {
case alerts.AlertLevelCritical:
return "🔴 CRITICAL"
case alerts.AlertLevelWarning:
return "🟡 WARNING"
default:
return "🟢 INFO"
}
}(),
alert.ResourceName,
)
req.Header.Set("Title", title)
priority := func() string {
switch alert.Level {
case alerts.AlertLevelCritical:
return "urgent"
case alerts.AlertLevelWarning:
return "high"
default:
return "default"
}
}()
req.Header.Set("Priority", priority)
tags := fmt.Sprintf("%s,pulse,%s",
func() string {
switch alert.Level {
case alerts.AlertLevelCritical:
return "rotating_light"
case alerts.AlertLevelWarning:
return "warning"
default:
return "white_check_mark"
}
}(),
alert.Type,
)
req.Header.Set("Tags", tags)
}
// Apply any custom headers from webhook config (these override defaults)
for key, value := range webhook.Headers {
req.Header.Set(key, value)
// Skip template-like headers (those with {{)
if !strings.Contains(value, "{{") {
req.Header.Set(key, value)
}
}
// Debug log the payload for Telegram and Gotify webhooks

View file

@ -284,9 +284,8 @@ func GetWebhookTemplates() []WebhookTemplate {
Method: "POST",
Headers: map[string]string{
"Content-Type": "text/plain",
"Title": "{{if eq .Level \"critical\"}}🔴 CRITICAL{{else if eq .Level \"warning\"}}🟡 WARNING{{else}}🟢 INFO{{end}}: {{.ResourceName}}",
"Priority": "{{if eq .Level \"critical\"}}urgent{{else if eq .Level \"warning\"}}high{{else}}default{{end}}",
"Tags": "{{if eq .Level \"critical\"}}rotating_light{{else if eq .Level \"warning\"}}warning{{else}}white_check_mark{{end}},pulse,{{.Type}}",
// Note: Title, Priority, and Tags headers should be added dynamically based on alert level
// For now, we'll use static reasonable defaults that won't break
},
PayloadTemplate: `{{if eq .Level "critical"}}🔴 CRITICAL{{else if eq .Level "warning"}}🟡 WARNING{{else}}🟢 INFO{{end}}: {{.ResourceName}} on {{.Node}}