feat: support webhook (#1187)

This commit is contained in:
Copilot authored and GitHub committed 2025-11-25 23:34:45 +08:00
1 parent 5bb8541385
commit 9d9f1caaaa
15 files changed
+1361 -33

No files matched your search

+115 -4
View File
@@ -6,10 +6,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/GopeedLab/gopeed/internal/test"
"github.com/GopeedLab/gopeed/pkg/base"
"github.com/GopeedLab/gopeed/pkg/download"
"github.com/GopeedLab/gopeed/pkg/rest/model"
"io"
"net"
"net/http"
@@ -20,6 +16,11 @@ import (
"sync"
"testing"
"time"
"github.com/GopeedLab/gopeed/internal/test"
"github.com/GopeedLab/gopeed/pkg/base"
"github.com/GopeedLab/gopeed/pkg/download"
"github.com/GopeedLab/gopeed/pkg/rest/model"
)
var (
@@ -606,6 +607,116 @@ func TestDoProxy(t *testing.T) {
})
}
func TestTestWebhook(t *testing.T) {
doTest(func() {
// Set up a mock webhook server
webhookReceived := false
var receivedData map[string]interface{}
var wg sync.WaitGroup
wg.Add(1)
webhookServer := http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
body, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
if err := json.Unmarshal(body, &receivedData); err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
// Check Content-Type
if r.Header.Get("Content-Type") != "application/json" {
t.Errorf("TestWebhook() Content-Type got = %v, want %v", r.Header.Get("Content-Type"), "application/json")
}
webhookReceived = true
w.WriteHeader(http.StatusOK)
wg.Done()
}),
}
// Start webhook server
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
webhookPort := listener.Addr().(*net.TCPAddr).Port
webhookURL := fmt.Sprintf("http://127.0.0.1:%d/webhook", webhookPort)
go webhookServer.Serve(listener)
defer webhookServer.Close()
// Test with valid webhook URL
httpRequestCheckOk[any](http.MethodPost, "/api/v1/webhook/test", &model.TestWebhookReq{
URL: webhookURL,
})
// Wait for webhook to be received
wg.Wait()
if !webhookReceived {
t.Error("TestWebhook() webhook was not received")
}
// Verify webhook data structure
if receivedData["event"] == nil {
t.Error("TestWebhook() missing 'event' field")
}
if receivedData["time"] == nil {
t.Error("TestWebhook() missing 'time' field")
}
if receivedData["payload"] == nil {
t.Error("TestWebhook() missing 'payload' field")
}
// Test with invalid webhook URL
code, _ := httpRequest[any](http.MethodPost, "/api/v1/webhook/test", &model.TestWebhookReq{
URL: "http://invalid-webhook-url-that-does-not-exist.local:99999/webhook",
})
checkCode(code, model.CodeError)
// Test with empty URL
code, _ = httpRequest[any](http.MethodPost, "/api/v1/webhook/test", &model.TestWebhookReq{
URL: "",
})
checkCode(code, model.CodeError)
// Test with webhook server returning non-200 status
wg.Add(1)
badWebhookServer := http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadRequest)
wg.Done()
}),
}
badListener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
badWebhookPort := badListener.Addr().(*net.TCPAddr).Port
badWebhookURL := fmt.Sprintf("http://127.0.0.1:%d/webhook", badWebhookPort)
go badWebhookServer.Serve(badListener)
defer badWebhookServer.Close()
code, _ = httpRequest[any](http.MethodPost, "/api/v1/webhook/test", &model.TestWebhookReq{
URL: badWebhookURL,
})
checkCode(code, model.CodeError)
wg.Wait()
})
}
func TestApiToken(t *testing.T) {
var cfg = &model.StartConfig{}
cfg.Init()