check / check (push) Successful in 6m32s
The receiver keeps the query string of the request it received on the event, in a new `raw_query` column of the per-webhook `events` table; a resubmitted copy carries its original's. The event log and the event's page show it with the request, the event log leaving out one over 32 KiB as it does request headers. The archive and log targets carry it. An HTTP target gets a `forwardQuery` setting, off by default, on both target forms and in the target list: on, each delivery, replays and resubmits included, appends the query string to the target URL, joined with `&` to one it already has. Model: opus-5-5
74 lines
1.9 KiB
Go
74 lines
1.9 KiB
Go
package delivery
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
"sneak.berlin/go/webhooker/internal/database"
|
|
)
|
|
|
|
// logTarget is a fire-and-forget target that logs the entire
|
|
// inbound webhook — the full request body, query string and
|
|
// headers, plus the method, content type, and the webhook and
|
|
// entrypoint ids — then records a single successful attempt.
|
|
//
|
|
// This is the one log call in the service that deliberately writes
|
|
// unbounded client-chosen bytes, so it is the one exception to the
|
|
// per-field budgets in internal/logfield and to the ceiling stated on
|
|
// middleware.MaxAccessLogLineBytes. Capping here would defeat the
|
|
// target: emitting the payload IS the delivery. It costs nothing by
|
|
// default — an authenticated operator has to create a target of this
|
|
// type on a specific webhook before a single line is written — and the
|
|
// bytes it writes are bounded per event by maxWebhookBodySize (1 MB).
|
|
// An operator who adds one is choosing to spend log volume on the
|
|
// payloads that webhook receives.
|
|
type logTarget struct {
|
|
eng *Engine
|
|
}
|
|
|
|
// Deliver implements Target.
|
|
func (t *logTarget) Deliver(
|
|
_ context.Context,
|
|
webhookDB *gorm.DB,
|
|
d *database.Delivery,
|
|
_ *Task,
|
|
_ Scheduler,
|
|
) {
|
|
start := time.Now()
|
|
|
|
t.eng.log.Info(
|
|
"webhook event delivered to log target",
|
|
"delivery_id", d.ID,
|
|
"event_id", d.EventID,
|
|
"target_id", d.TargetID,
|
|
"target_name", d.Target.Name,
|
|
"webhook_id", d.Event.WebhookID,
|
|
"entrypoint_id", d.Event.EntrypointID,
|
|
"method", d.Event.Method,
|
|
"raw_query", d.Event.RawQuery,
|
|
"content_type", d.Event.ContentType,
|
|
"headers", d.Event.Headers,
|
|
"body", d.Event.Body,
|
|
)
|
|
|
|
elapsed := time.Since(start)
|
|
|
|
t.eng.observeAttempt(d.Target.Type, elapsed)
|
|
|
|
err := t.eng.recordResult(
|
|
webhookDB, d, 1, true, 0, "", "",
|
|
elapsed.Milliseconds(),
|
|
)
|
|
if err != nil {
|
|
t.eng.bookkeepingFailed(d, err)
|
|
|
|
return
|
|
}
|
|
|
|
t.eng.settleStatus(
|
|
webhookDB, d, d.Target.Type,
|
|
database.DeliveryStatusDelivered,
|
|
)
|
|
}
|