Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions outputs/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ const (
)

type WebhookOutput struct {
Name string
Url string
Name string
Url string
Headers map[string][]string
}

func (webhook *WebhookOutput) GetType() string {
Expand Down Expand Up @@ -47,7 +48,22 @@ func (webhook *WebhookOutput) Init() error {
func (webhook *WebhookOutput) Send(content map[string]string) (data.OutputResponse, error) {
log.Logger.Infof("Sending webhook to %q", webhook.Url)
dataStr := content["description"] //it's not supposed to work with legacy renderer
resp, err := http.Post(webhook.Url, "application/json", strings.NewReader(dataStr))

req, err := http.NewRequest("POST", webhook.Url, strings.NewReader(dataStr))
if err != nil {
log.Logger.Errorf("Sending webhook Error: %v", err)
return data.OutputResponse{}, err
}
req.Header.Set("Content-Type", "application/json")

for key, values := range webhook.Headers {
for _, v := range values {
req.Header.Add(key, v)
}
}

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Logger.Errorf("Sending webhook Error: %v", err)
return data.OutputResponse{}, err
Expand Down
111 changes: 111 additions & 0 deletions outputs/webhook_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package outputs

import (
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
)

func TestWebhookOutput_Send_WithHeaders(t *testing.T) {
tests := []struct {
name string
headers map[string][]string
expectedHeaders map[string]string
}{
{
name: "Bearer token auth",
headers: map[string][]string{
"Authorization": {"Bearer test-token-123"},
},
expectedHeaders: map[string]string{
"Authorization": "Bearer test-token-123",
"Content-Type": "application/json",
},
},
{
name: "Basic auth",
headers: map[string][]string{
"Authorization": {"Basic dXNlcjpwYXNz"},
},
expectedHeaders: map[string]string{
"Authorization": "Basic dXNlcjpwYXNz",
"Content-Type": "application/json",
},
},
{
name: "No headers",
headers: nil,
expectedHeaders: map[string]string{
"Content-Type": "application/json",
},
},
{
name: "Multiple custom headers",
headers: map[string][]string{
"Authorization": {"Bearer token"},
"X-Custom": {"custom-value"},
},
expectedHeaders: map[string]string{
"Authorization": "Bearer token",
"X-Custom": "custom-value",
"Content-Type": "application/json",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var capturedHeaders http.Header

server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
capturedHeaders = r.Header
w.WriteHeader(http.StatusOK)
}))
defer server.Close()

webhook := &WebhookOutput{
Name: "test-webhook",
Url: server.URL,
Headers: tt.headers,
}

_, err := webhook.Send(map[string]string{"description": `{"test": "data"}`})
assert.NoError(t, err)

for key, expectedValue := range tt.expectedHeaders {
assert.Equal(t, expectedValue, capturedHeaders.Get(key), "Header %s mismatch", key)
}
})
}
}

func TestWebhookOutput_Send_ErrorCases(t *testing.T) {
t.Run("Bad URL", func(t *testing.T) {
webhook := &WebhookOutput{
Name: "test-webhook",
Url: "not-a-valid-url://invalid",
}

_, err := webhook.Send(map[string]string{"description": `{}`})
assert.Error(t, err)
})

t.Run("Server returns error status", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized)
_, _ = w.Write([]byte("Unauthorized"))
}))
defer server.Close()

webhook := &WebhookOutput{
Name: "test-webhook",
Url: server.URL,
}

_, err := webhook.Send(map[string]string{"description": `{}`})
assert.Error(t, err)
assert.Contains(t, err.Error(), "Unauthorized")
})
}
5 changes: 3 additions & 2 deletions router/builders.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ func buildSplunkOutput(sourceSettings *data.OutputSettings) *outputs.SplunkOutpu

func buildWebhookOutput(sourceSettings *data.OutputSettings) *outputs.WebhookOutput {
return &outputs.WebhookOutput{
Name: sourceSettings.Name,
Url: sourceSettings.Url,
Name: sourceSettings.Name,
Url: sourceSettings.Url,
Headers: sourceSettings.Headers,
}
}

Expand Down
Loading