From cd329a713cc24709029763c653baca4fd47b1eb2 Mon Sep 17 00:00:00 2001 From: Jayesh Bhade <52350067+Jaybhade@users.noreply.github.com> Date: Mon, 3 Aug 2026 20:40:27 +0530 Subject: [PATCH] fix: don't overwrite an Urgency header supplied via the headers option 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". --- src/web-push-lib.js | 11 ++++++++--- test/test-generate-request-details.js | 26 +++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/web-push-lib.js b/src/web-push-lib.js index 5e1343bf..7866b670 100644 --- a/src/web-push-lib.js +++ b/src/web-push-lib.js @@ -104,7 +104,7 @@ export class WebPushLib { let timeToLive = DEFAULT_TTL; let extraHeaders = {}; let contentEncoding = webPushConstants.supportedContentEncodings.AES_128_GCM; - let urgency = webPushConstants.supportedUrgency.NORMAL; + let urgency; let topic; let proxy; let agent; @@ -223,10 +223,13 @@ export class WebPushLib { timeToLive = DEFAULT_TTL; } + // Defaults are seeded first so that anything supplied through the + // `headers` option can override them. const requestDetails = { method: 'POST', headers: { - TTL: timeToLive + TTL: timeToLive, + Urgency: webPushConstants.supportedUrgency.NORMAL } }; Object.keys(extraHeaders).forEach(function (header) { @@ -292,7 +295,9 @@ export class WebPushLib { requestDetails.headers.Authorization = 'key=' + currentGCMAPIKey; } - requestDetails.headers.Urgency = urgency; + if (urgency) { + requestDetails.headers.Urgency = urgency; + } if (topic) { requestDetails.headers.Topic = topic; diff --git a/test/test-generate-request-details.js b/test/test-generate-request-details.js index 8918c188..916a466d 100644 --- a/test/test-generate-request-details.js +++ b/test/test-generate-request-details.js @@ -255,7 +255,9 @@ suite('Test Generate Request Details', function() { TTL: 100, headers: { 'Topic': 'topic', - 'Urgency': 'normal' + // Deliberately not the default urgency, so that this assertion can + // actually fail if the header is overwritten. + 'Urgency': 'high' } }; let details = generateRequestDetails( @@ -268,6 +270,28 @@ suite('Test Generate Request Details', function() { assert.equal(details.headers.Urgency, extraOptions.headers.Urgency); }); + test('Default urgency is used when no urgency is supplied', function() { + const subscription = { endpoint: 'https://127.0.0.1:8080' }; + + const details = generateRequestDetails(subscription, undefined, {}); + + assert.equal(details.headers.Urgency, 'normal'); + }); + + test('Urgency option takes precedence over an Urgency extra header', function() { + const subscription = { endpoint: 'https://127.0.0.1:8080' }; + const extraOptions = { + urgency: 'low', + headers: { + 'Urgency': 'high' + } + }; + + const details = generateRequestDetails(subscription, undefined, extraOptions); + + assert.equal(details.headers.Urgency, extraOptions.urgency); + }); + test('Audience contains port with aes128gcm', function() { const subscription = { endpoint: 'http://example.com:4242/life-universe-and-everything'