Skip to content

Commit

Permalink
Allow sending webhook notifications via GET (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
0x2142 committed Sep 18, 2024
1 parent 1fb7864 commit 667241e
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 20 deletions.
4 changes: 3 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ type Webhook struct {
Enabled bool `fig:"enabled" default:false`
Server string `fig:"server" default:""`
Insecure bool `fig:"ignoressl" default:false`
Method string `fig:"method" default:"POST"`
Params []map[string]string `fix:"params"`
Headers []map[string]string `fig:"headers"`
Template map[string]interface{} `fig:"template"`
}
Expand Down Expand Up @@ -262,7 +264,7 @@ func validateConfig() {
ConfigData.Frigate.StartupCheck.Interval = 30
}
for current_attempt < ConfigData.Frigate.StartupCheck.Attempts {
response, err = util.HTTPGet(statsAPI, ConfigData.Frigate.Insecure, ConfigData.Frigate.Headers...)
response, err = util.HTTPGet(statsAPI, ConfigData.Frigate.Insecure, "", ConfigData.Frigate.Headers...)
if err != nil {
log.Warn().
Err(err).
Expand Down
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
- Fixed issue where built-in alert templates were not being included in binary releases
- Fixed issue where a notification may not be sent if previous event update from Frigate did not contain a snapshot
- Added `from` & `ignoressl` config items to `smtp` notifier
- Added ability to send webhook notifications via HTTP GET requests
- Added support for URL parameters with webhook notifications

## [v0.3.4](https://github.com/0x2142/frigate-notify/releases/tag/v0.3.4) - Aug 15 2024
- Fixed issue where `unzoned: drop` config would drop all notifications
Expand Down
11 changes: 11 additions & 0 deletions docs/config/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -507,13 +507,22 @@ alerts:
- Required if this alerting method is enabled
- **ignoressl** (Optional - Default: `false`)
- Set to `true` to allow self-signed certificates
- **method** (Optional - Default: `POST`)
- Set HTTP method for webhook notifications
- Supports `GET` and `POST`
- **params** (Optional)
- Set optional HTTP params that will be appended to URL
- Params can utilize [template variables](./templates.md#available-variables)
- Format: `param: value`
- Example: `token: abcd1234`
- **headers** (Optional)
- Send additional HTTP headers to webhook receiver
- Header values can utilize [template variables](./templates.md#available-variables)
- Header format: `Header: Value`
- Example: `Authorization: Basic abcd1234`
- **template** (Optional)
- Optionally specify a custom notification template
- Only applies when `method` is `POST`
- For more information on template syntax, see [Alert Templates](./templates.md#alert-templates)
- Note: Webhook templates **must** be valid JSON

Expand All @@ -522,6 +531,8 @@ alerts:
enabled: false
server:
ignoressl:
method:
params:
headers:
template:
```
Expand Down
2 changes: 2 additions & 0 deletions docs/config/sample.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ alerts:
enabled: false
server:
ignoressl:
method:
params:
headers:
template:

Expand Down
4 changes: 2 additions & 2 deletions events/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func CheckForEvents() {
log.Debug().Msg("Checking for new events...")

// Query events
response, err := util.HTTPGet(url, config.ConfigData.Frigate.Insecure, config.ConfigData.Frigate.Headers...)
response, err := util.HTTPGet(url, config.ConfigData.Frigate.Insecure, "", config.ConfigData.Frigate.Headers...)
if err != nil {
log.Error().
Err(err).
Expand Down Expand Up @@ -115,7 +115,7 @@ func GetSnapshot(snapshotURL, eventID string) io.Reader {
q.Add("crop", "1")
}
url.RawQuery = q.Encode()
response, err := util.HTTPGet(url.String(), config.ConfigData.Frigate.Insecure, config.ConfigData.Frigate.Headers...)
response, err := util.HTTPGet(url.String(), config.ConfigData.Frigate.Insecure, "", config.ConfigData.Frigate.Headers...)
if err != nil {
log.Warn().
Str("event_id", eventID).
Expand Down
6 changes: 6 additions & 0 deletions example-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,12 @@ alerts:
server:
# Set to true to allow self-signed certificates
ignoressl:
# HTTP Method to send notifications, supports GET or POST (Default: POST)
method:
# Optional list of HTTP parameters to append to URL
params:
# Example:
# - token: abcd1234
# List of HTTP headers to send to webhook receiver, in format Header: Value
headers:
# Example:
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func main() {
log.Debug().Msg("App monitoring enabled.")
go func() {
for {
_, err := util.HTTPGet(config.ConfigData.Monitor.URL, config.ConfigData.Monitor.Insecure)
_, err := util.HTTPGet(config.ConfigData.Monitor.URL, config.ConfigData.Monitor.Insecure, "")
if err != nil {
log.Warn().
Err(err).
Expand Down
19 changes: 10 additions & 9 deletions notifier/alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,33 +108,34 @@ func renderMessage(sourceTemplate string, event models.Event) string {

}

// Build HTTP headers based on template
func renderHeaders(headers []map[string]string, event models.Event) []map[string]string {
// Build HTTP headers or params based on template
func renderHTTPKV(list []map[string]string, event models.Event, kvtype string) []map[string]string {
event = setExtras(event)
var newHeaders []map[string]string

for _, header := range headers {
for k, v := range header {
var renderedList []map[string]string

for _, item := range list {
for k, v := range item {
// Render
tmpl, err := template.New("custom").Funcs(template.FuncMap{"env": includeenv}).Parse(v)
if err != nil {
log.Warn().Err(err).Msg("Failed to render HTTP header")
log.Warn().Err(err).Msgf("Failed to render HTTP %s", kvtype)
}

var renderedTemplate bytes.Buffer
err = tmpl.Execute(&renderedTemplate, event)
if err != nil {
log.Fatal().
Err(err).
Msgf("Failed to render HTTP header")
Msgf("Failed to render HTTP %s", kvtype)
}

v = renderedTemplate.String()
newHeaders = append(newHeaders, map[string]string{k: v})
renderedList = append(renderedList, map[string]string{k: v})
}
}

return newHeaders
return renderedList
}

// includeenv retrieves environment variables for use within templates
Expand Down
2 changes: 1 addition & 1 deletion notifier/gotify.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func SendGotifyPush(event models.Event, snapshotURL string) {
gotifyURL := fmt.Sprintf("%s/message?token=%s&", config.ConfigData.Alerts.Gotify.Server, config.ConfigData.Alerts.Gotify.Token)

header := map[string]string{"Content-Type": "application/json"}
response, err := util.HTTPPost(gotifyURL, config.ConfigData.Alerts.Gotify.Insecure, data, header)
response, err := util.HTTPPost(gotifyURL, config.ConfigData.Alerts.Gotify.Insecure, data, "", header)
if err != nil {
log.Warn().
Str("event_id", event.ID).
Expand Down
4 changes: 2 additions & 2 deletions notifier/nfty.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ func SendNtfyPush(event models.Event, snapshot io.Reader) {
headers = append(headers, map[string]string{"X-Actions": "view, View Clip, " + clip + ", clear=true"})
}

headers = renderHeaders(headers, event)
headers = renderHTTPKV(headers, event, "headers")

resp, err := util.HTTPPost(NtfyURL, config.ConfigData.Alerts.Ntfy.Insecure, attachment, headers...)
resp, err := util.HTTPPost(NtfyURL, config.ConfigData.Alerts.Ntfy.Insecure, attachment, "", headers...)
if err != nil {
log.Warn().
Str("event_id", event.ID).
Expand Down
14 changes: 12 additions & 2 deletions notifier/webhook.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package notifier

import (
"strings"

"github.com/disgoorg/json"
"github.com/rs/zerolog/log"

Expand Down Expand Up @@ -33,8 +35,16 @@ func SendWebhook(event models.Event) {
message = renderMessage("json", event)
}

headers := renderHeaders(config.ConfigData.Alerts.Webhook.Headers, event)
_, err = util.HTTPPost(config.ConfigData.Alerts.Webhook.Server, config.ConfigData.Alerts.Webhook.Insecure, []byte(message), headers...)
headers := renderHTTPKV(config.ConfigData.Alerts.Webhook.Headers, event, "headers")
params := renderHTTPKV(config.ConfigData.Alerts.Webhook.Params, event, "params")
paramString := util.BuildHTTPParams(params...)
if strings.ToUpper(config.ConfigData.Alerts.Webhook.Method) == "GET" {
_, err = util.HTTPGet(config.ConfigData.Alerts.Webhook.Server, config.ConfigData.Alerts.Webhook.Insecure, paramString, headers...)

} else {
_, err = util.HTTPPost(config.ConfigData.Alerts.Webhook.Server, config.ConfigData.Alerts.Webhook.Insecure, []byte(message), paramString, headers...)
}

if err != nil {
log.Warn().
Str("event_id", event.ID).
Expand Down
33 changes: 31 additions & 2 deletions util/httpclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,40 @@ import (
"bytes"
"crypto/tls"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"time"

"github.com/rs/zerolog/log"
)

// buildParams creates an escaped param string from a slice
func BuildHTTPParams(params ...map[string]string) string {
var paramList string
if len(params) > 0 {
paramList = "?"
for _, h := range params {
for k, v := range h {
k = url.QueryEscape(k)
v = url.QueryEscape(v)
paramList = fmt.Sprintf("%s&%s=%s", paramList, k, v)
}

}
}

return paramList
}

// HTTPGet is a simple HTTP client function to return page body
func HTTPGet(url string, insecure bool, headers ...map[string]string) ([]byte, error) {
func HTTPGet(url string, insecure bool, params string, headers ...map[string]string) ([]byte, error) {
// Append HTTP params if any
if len(params) > 0 {
url = url + params
}

// New HTTP Client
client := http.Client{Timeout: 10 * time.Second}
Expand Down Expand Up @@ -61,7 +85,12 @@ func HTTPGet(url string, insecure bool, headers ...map[string]string) ([]byte, e

// HTTPPost performs an HTTP POST to the target URL
// and includes auth parameters, ignoring certificates, etc
func HTTPPost(url string, insecure bool, payload []byte, headers ...map[string]string) ([]byte, error) {
func HTTPPost(url string, insecure bool, payload []byte, params string, headers ...map[string]string) ([]byte, error) {
// Append HTTP params if any
if len(params) > 0 {
url = url + params
}

// New HTTP Client
client := http.Client{Timeout: 10 * time.Second}

Expand Down

0 comments on commit 667241e

Please sign in to comment.