Move webhook pages to /hook/ID and inbound URLs to /h/UUID (closes #367)
check / check (push) Successful in 4m23s

The webhook page and everything under it move from /source/ID to
/hook/ID, the list and new-webhook form to /hooks and /hooks/new, and
the event log from .../logs to /hook/ID/events, body download
included. Entrypoint URLs move from /webhook/UUID to /h/UUID, and the
webhook page shows only that form. The old paths are gone.

Links, redirects, form actions, tests, comments and the README follow.
Go identifiers and template file names are unchanged. A new route test
posts to the entrypoint URL the webhook page shows and checks that the
receiver rate limit applies to it.

Model: opus-5-5
This commit is contained in:
2026-10-01 19:13:32 +00:00
parent b79e4649a1
commit cf795ff5df
46 changed files with 266 additions and 218 deletions
+6 -6
View File
@@ -28,7 +28,7 @@ const (
// receiverRoutePattern is the one handler label every receiver
// request must produce, however the client varies the path.
receiverRoutePattern = "/webhook/{uuid}"
receiverRoutePattern = "/h/{uuid}"
// okRoute is a static route used to pin that the response-writer
// interceptor still reports status and size after the handler id
@@ -143,13 +143,13 @@ func drivePaths(
return drive(t, h, probes)
}
// receiverPaths returns n distinct /webhook/ paths, each naming a
// receiverPaths returns n distinct /h/ paths, each naming a
// fresh UUID exactly as an unauthenticated flood would.
func receiverPaths(n int) []string {
paths := make([]string, 0, n)
for range n {
paths = append(paths, "/webhook/"+uuid.NewString())
paths = append(paths, "/h/"+uuid.NewString())
}
return paths
@@ -220,7 +220,7 @@ func keys(set map[string]struct{}) []string {
// TestMetrics_DistinctReceiverPathsMintOneLabelSet is the direct
// assertion the issue asks for: N requests to N distinct
// /webhook/<uuid> paths must produce exactly ONE handler label, the
// /h/<uuid> paths must produce exactly ONE handler label, the
// route pattern. Before the fix this produced N of them.
func TestMetrics_DistinctReceiverPathsMintOneLabelSet(t *testing.T) {
t.Parallel()
@@ -250,7 +250,7 @@ func TestMetrics_DistinctReceiverPathsMintOneLabelSet(t *testing.T) {
// The scrape must not republish the UUIDs it was driven with.
// They are the receiver's only credential.
for _, p := range paths {
id := strings.TrimPrefix(p, "/webhook/")
id := strings.TrimPrefix(p, "/h/")
for label := range labels {
assert.NotContains(
t, label, id,
@@ -354,7 +354,7 @@ func TestMetrics_UnmatchedPathsCollapseToTheSentinel(t *testing.T) {
if i%2 == 0 {
paths = append(paths, "/"+id)
} else {
paths = append(paths, "/webhook/"+id+"/"+id)
paths = append(paths, "/h/"+id+"/"+id)
}
}