Send Content-Type once on a delivery #331

Merged
clawbot merged 2 commits from issue-246-single-content-type into next 2026-09-29 07:11:56 +02:00
Collaborator

Fixes #246.

A delivery to an HTTP target could carry two Content-Type values: applyRequestHeaders set it from the event's ContentType, then the inbound Content-Type from the event's stored headers was added on top. Now the inbound Content-Type is never copied from the stored headers (isForwardableHeader returns false for it). The receiver already saves that same value as the event's ContentType, so nothing is lost.

Which value goes out is now stated in the comment on applyRequestHeaders:

  1. a Content-Type configured on the target;
  2. otherwise the event's ContentType;
  3. otherwise none.

Redirects: the delete(originScoped, "Content-Type") stays. Only a Content-Type configured on the target can reach that set now, and it must still survive a cross-origin 307/308 with the body. Its comment now says that.

The new test checks the outbound request has exactly one value in four cases: inbound and event agree, they disagree (the event's wins), the event has none (none is sent), and the target configures its own (that one wins).

  • Behaviour change: an event with an empty ContentType whose stored headers carry a Content-Type is now delivered with no Content-Type at all, as the plan specified.
  • The case where the target configures its own Content-Type already gave one value before this change. The test keeps it as a guard on the stated order.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/webhooker/issues/246. A delivery to an HTTP target could carry two `Content-Type` values: `applyRequestHeaders` set it from the event's `ContentType`, then the inbound `Content-Type` from the event's stored headers was added on top. Now the inbound `Content-Type` is never copied from the stored headers (`isForwardableHeader` returns false for it). The receiver already saves that same value as the event's `ContentType`, so nothing is lost. Which value goes out is now stated in the comment on `applyRequestHeaders`: 1. a `Content-Type` configured on the target; 2. otherwise the event's `ContentType`; 3. otherwise none. Redirects: the `delete(originScoped, "Content-Type")` stays. Only a `Content-Type` configured on the target can reach that set now, and it must still survive a cross-origin 307/308 with the body. Its comment now says that. The new test checks the outbound request has exactly one value in four cases: inbound and event agree, they disagree (the event's wins), the event has none (none is sent), and the target configures its own (that one wins). - Behaviour change: an event with an empty `ContentType` whose stored headers carry a `Content-Type` is now delivered with no `Content-Type` at all, as the plan specified. - The case where the target configures its own `Content-Type` already gave one value before this change. The test keeps it as a guard on the stated order. Model: opus-5-5
clawbot added the needs-review label 2026-09-29 05:58:01 +02:00
clawbot self-assigned this 2026-09-29 05:58:02 +02:00
Author
Collaborator
  • internal/delivery/redirect_test.go, TestApplyRequestHeaders_ReportsOriginScopedNames: after this PR, nothing tests delete(originScoped, "Content-Type") in applyRequestHeaders (internal/delivery/target_http.go). This test used to be that line's only coverage, but its fixture puts Content-Type only in the event's stored headers, and isForwardableHeader now drops that earlier, so removing the line fails no test. A later change that strips a target-configured Content-Type on a cross-origin 307/308 would go unnoticed. The test's comment also still says Content-Type is left out because a 307 carries the body, which is no longer why it is missing. Acceptable: configure a Content-Type on the target in that test and assert it is not among the returned names, and have its comment say the inbound Content-Type is absent because it is not forwarded.

Model: opus-5-5

- `internal/delivery/redirect_test.go`, `TestApplyRequestHeaders_ReportsOriginScopedNames`: after this PR, nothing tests `delete(originScoped, "Content-Type")` in `applyRequestHeaders` (`internal/delivery/target_http.go`). This test used to be that line's only coverage, but its fixture puts `Content-Type` only in the event's stored headers, and `isForwardableHeader` now drops that earlier, so removing the line fails no test. A later change that strips a target-configured `Content-Type` on a cross-origin 307/308 would go unnoticed. The test's comment also still says `Content-Type` is left out because a 307 carries the body, which is no longer why it is missing. Acceptable: configure a `Content-Type` on the target in that test and assert it is not among the returned names, and have its comment say the inbound `Content-Type` is absent because it is not forwarded. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-09-29 06:09:34 +02:00
clawbot added 2 commits 2026-09-29 06:18:49 +02:00
A delivery set Content-Type from the event's ContentType and then
added the inbound Content-Type from the event's stored headers, so
the target could receive two values. The inbound Content-Type is no
longer forwarded from the stored headers; the receiver already saved
it as the event's ContentType.

Which value wins is now stated at applyRequestHeaders: a Content-Type
configured on the target, otherwise the event's ContentType,
otherwise none.

Model: opus-5-5
TestApplyRequestHeaders_ReportsOriginScopedNames now configures a
Content-Type on the target and asserts it is not among the returned
names, so dropping the delete in applyRequestHeaders fails it. Its
comment now says the inbound Content-Type is absent because it is not
forwarded.

Model: opus-5-5
clawbot force-pushed issue-246-single-content-type from 306c2cb9b1 to 2ae6f4be30 2026-09-29 06:18:49 +02:00 Compare
Author
Collaborator

TestApplyRequestHeaders_ReportsOriginScopedNames now configures a Content-Type on the target and asserts it is not among the returned names; its comment says the inbound Content-Type is absent because it is not forwarded.
The first commit was recorded under the owner's identity; its author and committer are now clawbot, content unchanged.

Model: opus-5-5

`TestApplyRequestHeaders_ReportsOriginScopedNames` now configures a `Content-Type` on the target and asserts it is not among the returned names; its comment says the inbound `Content-Type` is absent because it is not forwarded. The first commit was recorded under the owner's identity; its author and committer are now `clawbot`, content unchanged. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-09-29 06:18:58 +02:00
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot merged commit d4f4ddf51f into next 2026-09-29 07:11:56 +02:00
clawbot deleted branch issue-246-single-content-type 2026-09-29 07:11:56 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#331