mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-16 20:32:13 +01:00
feat(webhook): add events
This commit is contained in:
@@ -181,7 +181,7 @@ func (s *scenario) iMakeARequestToGotenbergWithTheFollowingFormDataAndHeaders(ct
|
||||
}
|
||||
files[name] = append(files[name], value)
|
||||
case "header":
|
||||
if name == "Gotenberg-Webhook-Url" || name == "Gotenberg-Webhook-Error-Url" {
|
||||
if name == "Gotenberg-Webhook-Url" || name == "Gotenberg-Webhook-Error-Url" || name == "Gotenberg-Webhook-Events-Url" {
|
||||
headers[name] = fmt.Sprintf(value, s.hostPort)
|
||||
continue
|
||||
}
|
||||
@@ -653,6 +653,48 @@ func (s *scenario) theBodyShouldMatchJSON(kind string, expectedDoc *godog.DocStr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *scenario) theWebhookEventShouldMatchJSON(ctx context.Context, expectedDoc *godog.DocString) error {
|
||||
if s.server == nil {
|
||||
return errors.New("server not initialized")
|
||||
}
|
||||
|
||||
// Poll briefly — the event fires right after the main webhook.
|
||||
var body []byte
|
||||
deadline := time.After(5 * time.Second)
|
||||
for {
|
||||
body = s.server.getEventBody()
|
||||
if body != nil {
|
||||
break
|
||||
}
|
||||
select {
|
||||
case <-deadline:
|
||||
return errors.New("timed out waiting for webhook event")
|
||||
default:
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
var expected, actual any
|
||||
|
||||
content := strings.ReplaceAll(expectedDoc.Content, "{version}", GotenbergVersion)
|
||||
err := json.Unmarshal([]byte(content), &expected)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unmarshal expected JSON: %w", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, &actual)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unmarshal actual JSON: %w", err)
|
||||
}
|
||||
|
||||
err = compareJson(expected, actual)
|
||||
if err != nil {
|
||||
return fmt.Errorf("expected matching webhook event JSON: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *scenario) thereShouldBePdfs(expected int, kind string) error {
|
||||
dirPath := s.teststoreDir
|
||||
|
||||
@@ -1158,6 +1200,7 @@ func InitializeScenario(ctx *godog.ScenarioContext) {
|
||||
ctx.Then(`^the (response|webhook request) body should match string:$`, s.theBodyShouldMatchString)
|
||||
ctx.Then(`^the (response|webhook request) body should contain string:$`, s.theBodyShouldContainString)
|
||||
ctx.Then(`^the (response|webhook request) body should match JSON:$`, s.theBodyShouldMatchJSON)
|
||||
ctx.Then(`^the webhook event should match JSON:$`, s.theWebhookEventShouldMatchJSON)
|
||||
ctx.Then(`^there should be (\d+) PDF\(s\) in the (response|webhook request)$`, s.thereShouldBePdfs)
|
||||
ctx.Then(`^there should be the following file\(s\) in the (response|webhook request):$`, s.thereShouldBeTheFollowingFiles)
|
||||
ctx.Then(`^the (response|webhook request) PDF\(s\) should be valid "([^"]*)" with a tolerance of (\d+) failed rule\(s\)$`, s.thePdfsShouldBeValidWithAToleranceOf)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/cucumber/godog"
|
||||
"github.com/google/uuid"
|
||||
@@ -19,10 +20,12 @@ import (
|
||||
)
|
||||
|
||||
type server struct {
|
||||
srv *echo.Echo
|
||||
req *http.Request
|
||||
bodyCopy []byte
|
||||
errChan chan error
|
||||
srv *echo.Echo
|
||||
req *http.Request
|
||||
bodyCopy []byte
|
||||
errChan chan error
|
||||
eventBody []byte
|
||||
eventMu sync.Mutex
|
||||
}
|
||||
|
||||
func newServer(ctx context.Context, workdir string) (*server, error) {
|
||||
@@ -144,6 +147,18 @@ func newServer(ctx context.Context, workdir string) (*server, error) {
|
||||
srv.POST("/webhook/error", webhookErrorHandler)
|
||||
srv.PATCH("/webhook/error", webhookErrorHandler)
|
||||
srv.PUT("/webhook/error", webhookErrorHandler)
|
||||
|
||||
webhookEventsHandler := func(c echo.Context) error {
|
||||
body, err := io.ReadAll(c.Request().Body)
|
||||
if err != nil {
|
||||
return c.String(http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
s.eventMu.Lock()
|
||||
s.eventBody = body
|
||||
s.eventMu.Unlock()
|
||||
return c.String(http.StatusOK, http.StatusText(http.StatusOK))
|
||||
}
|
||||
srv.POST("/webhook/events", webhookEventsHandler)
|
||||
srv.GET("/static/:path", func(c echo.Context) error {
|
||||
s.req = c.Request()
|
||||
path := c.Param("path")
|
||||
@@ -170,6 +185,12 @@ func newServer(ctx context.Context, workdir string) (*server, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *server) getEventBody() []byte {
|
||||
s.eventMu.Lock()
|
||||
defer s.eventMu.Unlock()
|
||||
return s.eventBody
|
||||
}
|
||||
|
||||
func (s *server) start(ctx context.Context) (int, error) {
|
||||
// #nosec
|
||||
ln, err := net.Listen("tcp", "0.0.0.0:0")
|
||||
|
||||
Reference in New Issue
Block a user