Skip to content

fix: don't overwrite an Urgency header supplied via the headers option - #980

Open
Jaybhade wants to merge 1 commit into
web-push-libs:masterfrom
Jaybhade:fix/respect-urgency-extra-header
Open

fix: don't overwrite an Urgency header supplied via the headers option#980
Jaybhade wants to merge 1 commit into
web-push-libs:masterfrom
Jaybhade:fix/respect-urgency-extra-header

Conversation

@Jaybhade

@Jaybhade Jaybhade commented Aug 3, 2026

Copy link
Copy Markdown

generateRequestDetails() copies the headers option into the outgoing request headers, and then unconditionally reassigns Urgency from the urgency option — which defaults to normal. So whatever the caller put in headers is thrown away:

webpush.generateRequestDetails(subscription, undefined, {
  headers: { Urgency: 'high' }
}).headers.Urgency;
// => 'normal'

No error and no warning; the notification just goes out at normal urgency. The sibling Topic header doesn't have this problem, because it is only written when the topic option is actually set — headers: { Topic: 'mytopic' } survives.

This seeds the default urgency into the headers object before the headers option is applied, and only writes the option-derived value when one was supplied. Urgency then gets exactly the same precedence Topic already has:

  • the urgency option wins when it is given,
  • otherwise an Urgency entry in headers is used,
  • otherwise it falls back to normal.

One note on the existing coverage: the Extra headers test already asserted this, but passed 'normal' as the header value — the same value the overwrite put back — so the assertion could never fail. It now uses 'high', which fails on master and passes here. I also added two tests pinning the default and the option-wins precedence.

Two things I deliberately left alone, happy to fold either in if you'd rather:

  • The duplicated-headers guard. It compares header names against option keys case-sensitively, so headers: { Urgency } plus urgency doesn't trip it (same for Topic/topic). Making it case-insensitive would start throwing for combinations that are accepted today, which felt like a separate decision from this bug.
  • Validation of a headers-supplied urgency. Values arriving through headers are passed through as-is, so an Urgency set that way isn't checked against the four allowed values — consistent with how Topic behaves today.

Verification: npm run lint is clean, and the full non-browser suite passes (79 tests across test-generate-request-details, test-vapid-helper, test-set-vapid-details, test-encryption-helper, testSetGCMAPIKey, testSendNotification and test-cli).

generateRequestDetails() copied the `headers` option into the request
headers and then unconditionally reassigned `Urgency` to the value of
the `urgency` option, which defaults to "normal". A caller asking for
`headers: { Urgency: 'high' }` therefore had it silently downgraded to
"normal" on the wire, with no error and no warning.

The sibling `Topic` header did not have this problem, because it is only
written when the `topic` option is actually set.

Seed the default urgency into the headers object before the `headers`
option is applied, and only write the option-derived value when one was
supplied. That gives Urgency the same precedence as Topic: the explicit
option wins, an extra header is used when no option is given, and
"normal" remains the default when neither is.

The existing 'Extra headers' test asserted this exact behaviour, but
passed "normal" as the header value -- the same value the overwrite put
back -- so it could never fail. It now uses "high".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant