internal/rest/test_event.go
Rama main · réplica de lectura del repositorio original.
package rest
import (
"context"
"net/http"
"github.com/danielgtaylor/huma/v2"
"github.com/sarathsp06/sparrow/internal/webhooks"
)
type sendTestEventInput struct {
Consumer string `path:"consumer" doc:"Tenant consumer the subscription belongs to."`
SubscriptionID string `path:"subscription_id" doc:"Subscription to send the event to: its transform renders the payload, and its webhook receives it."`
Body struct {
EventName string `json:"event_name" required:"true" doc:"Event to send: the subscription's event, or any event for a catch-all (*) subscription."`
Payload map[string]any `json:"payload,omitempty" doc:"Event payload to send instead of the event type's sample payload. It is rendered through the subscription's transform like a pushed event."`
}
}
type sendTestEventOutput struct {
Body struct {
StatusCode int `json:"status_code" doc:"The receiver's HTTP status; 0 when no response was received."`
LatencyMs int64 `json:"latency_ms" doc:"Time to the response headers, in milliseconds."`
ErrorClass string `json:"error_class,omitempty" doc:"Delivery error category when the send did not get a 2xx: client_error, server_error, rate_limited, timeout, connection_refused, dns_error, tls_error, network_error, redirect, template_error (nothing was sent) or unknown."`
}
}
func registerTestEventRoutes(api huma.API, svc webhooks.TestEventSender) {
huma.Register(api, huma.Operation{
OperationID: "sendTestEvent",
Method: http.MethodPost,
Path: "/v1/consumers/{consumer}/subscriptions/{subscription_id}:sendTestEvent",
Summary: "Send a test event to a subscription",
Description: "Sends event_name to the subscription: one signed delivery of payload, or of the event type's sample when payload is omitted, rendered through the subscription's transform as a real delivery would be, to its webhook's URL, synchronously, and returns what the receiver answered. " +
"It uses the same request builder, signing, network policy (SSRF protection) and timeout as real deliveries and adds the header X-Sparrow-Test: true. " +
"It creates no delivery and never counts toward the webhook's health or auto-disable. A receiver error is reported in the response (status_code, error_class), not as an API error.\n\n" +
"One test event per webhook every 2 seconds on each server: more answer 429. 404 for a subscription not in this consumer. 400 when the subscription does not receive event_name, or when the event type is not registered and no payload is given.\n\nPortal tokens: allowed, as POST /portal/api/subscriptions/{subscription_id}:sendTestEvent.",
Errors: []int{400, 404, 429, 503},
Tags: []string{"Subscriptions"},
}, func(ctx context.Context, in *sendTestEventInput) (*sendTestEventOutput, error) {
res, err := svc.SendTestEvent(ctx, in.Consumer, in.SubscriptionID, in.Body.EventName, in.Body.Payload)
if err != nil {
return nil, mapError(ctx, err, "failed to send the test event")
}
out := &sendTestEventOutput{}
out.Body.StatusCode = res.StatusCode
out.Body.LatencyMs = res.Latency.Milliseconds()
out.Body.ErrorClass = res.ErrorClass
return out, nil
})
}