Store and show an event's query string, and pass it on to an HTTP target when set (closes #312)
check / check (push) Successful in 4m45s

The receiver dropped the query string of every request it received, so a sender's URL parameters were silently lost. Each event now keeps it, as sent, 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 in the shared request block, the event log leaving out one over 32 KiB with a link, as for headers. The archive and log targets carry it. HTTP targets gain "Pass the query string on to this target", off by default: on, deliveries, replays and resubmits append it to the target URL, joined with `&` to one already there. The access log still hides it.

Model: opus-5-5
This commit was merged in pull request #501.
This commit is contained in:
2026-10-04 03:00:34 +02:00
parent a8fc0c5d32
commit ea8cba7264
32 changed files with 537 additions and 69 deletions
+18 -13
View File
@@ -173,6 +173,9 @@ type targetFormInput struct {
Headers string
// Timeout is an HTTP target's per-request timeout in seconds.
Timeout string
// ForwardQuery is an HTTP target's checkbox that passes each
// event's query string on to it.
ForwardQuery bool
// MaxRetries is an HTTP or Slack target's max_retries.
MaxRetries string
// Expiry is a database (archive) target's row expiry.
@@ -195,14 +198,15 @@ type targetFormInput struct {
// tokens.
func targetFormInputFrom(r *http.Request) targetFormInput {
return targetFormInput{
Name: r.PostFormValue("name"),
Type: database.TargetType(r.PostFormValue("type")),
URL: r.PostFormValue("url"),
Headers: r.PostFormValue("headers"),
Timeout: r.PostFormValue("timeout"),
MaxRetries: r.PostFormValue("max_retries"),
Expiry: r.PostFormValue("expiry"),
Rotation: r.PostFormValue("rotation"),
Name: r.PostFormValue("name"),
Type: database.TargetType(r.PostFormValue("type")),
URL: r.PostFormValue("url"),
Headers: r.PostFormValue("headers"),
Timeout: r.PostFormValue("timeout"),
ForwardQuery: r.PostFormValue("forward_query") != "",
MaxRetries: r.PostFormValue("max_retries"),
Expiry: r.PostFormValue("expiry"),
Rotation: r.PostFormValue("rotation"),
}
}
@@ -232,8 +236,8 @@ func (h *Handlers) buildTargetConfig(
}
// buildHTTPTargetConfig builds config JSON for an HTTP target: an
// SSRF-validated destination plus the optional headers and timeout
// the delivery path honours.
// SSRF-validated destination plus the optional headers, timeout and
// query string setting the delivery path honours.
func (h *Handlers) buildHTTPTargetConfig(
ctx context.Context,
in targetFormInput,
@@ -256,9 +260,10 @@ func (h *Handlers) buildHTTPTargetConfig(
}
configJSON, err := marshalTargetConfig(delivery.HTTPTargetConfig{
URL: in.URL,
Headers: headers,
Timeout: timeout,
URL: in.URL,
Headers: headers,
Timeout: timeout,
ForwardQuery: in.ForwardQuery,
})
return configJSON, "", err