Skip to content

http2: remove support for priority signaling #58293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -3945,15 +3945,17 @@ an internal nodejs implementation rather than a public facing API, use `node:str

<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/58293
description: End-of-Life.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/58313
description: Documentation-only deprecation.
-->

Type: Documentation-only
Type: End-of-Life

The support for priority signaling has been deprecated in the [RFC 9113][], and
will be removed in future versions of Node.js.
The support for priority signaling has been removed following its deprecation in the [RFC 9113][].

[DEP0142]: #dep0142-repl_builtinlibs
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
Expand Down
41 changes: 16 additions & 25 deletions doc/api/http2.md
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,10 @@ The `'origin'` event is only emitted when using a secure TLS connection.
<!-- YAML
added: v8.4.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/58293
description: The `weight` option is now ignored, setting it will trigger a
runtime warning.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/58313
description: Following the deprecation of priority signaling as of RFC 1993,
Expand All @@ -1090,10 +1094,6 @@ changes:
**Default:** `false`.
* `parent` {number} Specifies the numeric identifier of a stream the newly
created stream is dependent on.
* `weight` {number} Specifies the relative dependency of a stream in relation
to other streams with the same `parent`. The value is a number between `1`
and `256` (inclusive). This has been **deprecated** in [RFC 9113][], and
support for it will be removed in future versions of Node.js.
* `waitForTrailers` {boolean} When `true`, the `Http2Stream` will emit the
`'wantTrailers'` event after the final `DATA` frame has been sent.
* `signal` {AbortSignal} An AbortSignal that may be used to abort an ongoing
Expand Down Expand Up @@ -1464,25 +1464,17 @@ numeric stream identifier.
<!-- YAML
added: v8.4.0
deprecated: REPLACEME
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/58293
description: This method no longer sets the priority of the stream. Using it
now triggers a runtime warning.
-->

> Stability: 0 - Deprecated: support for priority signaling has been deprecated
> in the [RFC 9113][] and is no longer supported in Node.js.

* `options` {Object}
* `exclusive` {boolean} When `true` and `parent` identifies a parent Stream,
this stream is made the sole direct dependency of the parent, with
all other existing dependents made a dependent of this stream. **Default:**
`false`.
* `parent` {number} Specifies the numeric identifier of a stream this stream
is dependent on.
* `weight` {number} Specifies the relative dependency of a stream in relation
to other streams with the same `parent`. The value is a number between `1`
and `256` (inclusive).
* `silent` {boolean} When `true`, changes the priority locally without
sending a `PRIORITY` frame to the connected peer.

Updates the priority for this `Http2Stream` instance.
Empty method, only there to maintain some backward compatibility.

#### `http2stream.rstCode`

Expand Down Expand Up @@ -1579,6 +1571,10 @@ req.setTimeout(5000, () => req.close(NGHTTP2_CANCEL));
<!-- YAML
added: v8.4.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/58293
description: The `state.weight` property is now always set to 16 and
`sumDependencyWeight` is always set to 0.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/58313
description: Following the deprecation of priority signaling as of RFC 1993,
Expand All @@ -1596,13 +1592,8 @@ Provides miscellaneous information about the current state of the
* `localClose` {number} `1` if this `Http2Stream` has been closed locally.
* `remoteClose` {number} `1` if this `Http2Stream` has been closed
remotely.
* `sumDependencyWeight` {number} The sum weight of all `Http2Stream`
instances that depend on this `Http2Stream` as specified using
`PRIORITY` frames. This has been **deprecated** in [RFC 9113][], and
support for it will be removed in future versions of Node.js.
* `weight` {number} The priority weight of this `Http2Stream`. This has been
**deprecated** in [RFC 9113][], and support for it will be removed in future
versions of Node.js.
* `sumDependencyWeight` {number} Legacy property, always set to `0`.
* `weight` {number} Legacy property, always set to `16`.

A current state of this `Http2Stream`.

Expand Down
61 changes: 17 additions & 44 deletions lib/internal/http2/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const {
customInspectSymbol: kInspect,
kEmptyObject,
promisify,
deprecate,
deprecateProperty,
} = require('internal/util');

assertCrypto();
Expand Down Expand Up @@ -746,6 +748,11 @@ function onGoawayData(code, lastStreamID, buf) {
}
}

// TODO(aduh95): remove this in future semver-major
const deprecateWeight = deprecateProperty('weight',
'Priority signaling has been deprecated as of RFC 1993.',
'DEP0194');

// When a ClientHttp2Session is first created, the socket may not yet be
// connected. If request() is called during this time, the actual request
// will be deferred until the socket is ready to go.
Expand Down Expand Up @@ -774,12 +781,14 @@ function requestOnConnect(headersList, headersParam, options) {
if (options.waitForTrailers)
streamOptions |= STREAM_OPTION_GET_TRAILERS;

deprecateWeight(options);

// `ret` will be either the reserved stream ID (if positive)
// or an error code (if negative)
const ret = session[kHandle].request(headersList,
streamOptions,
options.parent | 0,
options.weight | 0,
NGHTTP2_DEFAULT_WEIGHT,
!!options.exclusive);

// In an error condition, one of three possible response codes will be
Expand Down Expand Up @@ -824,11 +833,7 @@ function requestOnConnect(headersList, headersParam, options) {
//
// Also sets the default priority options if they are not set.
const setAndValidatePriorityOptions = hideStackFrames((options) => {
if (options.weight === undefined) {
options.weight = NGHTTP2_DEFAULT_WEIGHT;
} else {
validateNumber.withoutStackTrace(options.weight, 'options.weight');
}
deprecateWeight(options);

if (options.parent === undefined) {
options.parent = 0;
Expand Down Expand Up @@ -884,25 +889,6 @@ function submitSettings(settings, callback) {
}
}

// Submits a PRIORITY frame to be sent to the remote peer
// Note: If the silent option is true, the change will be made
// locally with no PRIORITY frame sent.
function submitPriority(options) {
if (this.destroyed)
return;
this[kUpdateTimer]();

// If the parent is the id, do nothing because a
// stream cannot be made to depend on itself.
if (options.parent === this[kID])
return;

this[kHandle].priority(options.parent | 0,
options.weight | 0,
!!options.exclusive,
!!options.silent);
}

// Submit a GOAWAY frame to be sent to the remote peer.
// If the lastStreamID is set to <= 0, then the lastProcStreamID will
// be used. The opaqueData must either be a typed array or undefined
Expand Down Expand Up @@ -2312,25 +2298,6 @@ class Http2Stream extends Duplex {
}
}

priority(options) {
if (this.destroyed)
throw new ERR_HTTP2_INVALID_STREAM();

assertIsObject(options, 'options');
options = { ...options };
setAndValidatePriorityOptions(options);

const priorityFn = submitPriority.bind(this, options);

// If the handle has not yet been assigned, queue up the priority
// frame to be sent as soon as the ready event is emitted.
if (this.pending) {
this.once('ready', priorityFn);
return;
}
priorityFn();
}

sendTrailers(headers) {
if (this.destroyed || this.closed)
throw new ERR_HTTP2_INVALID_STREAM();
Expand Down Expand Up @@ -2496,6 +2463,12 @@ class Http2Stream extends Duplex {
}
}

// TODO(aduh95): remove this in future semver-major
Http2Stream.prototype.priority = deprecate(function priority(options) {
if (this.destroyed)
throw new ERR_HTTP2_INVALID_STREAM();
}, 'http2Stream.priority is longer supported after priority signalling was deprecated in RFC 1993', 'DEP0194');

function callTimeout(self, session) {
// If the session is destroyed, this should never actually be invoked,
// but just in case...
Expand Down
12 changes: 12 additions & 0 deletions lib/internal/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ function isPendingDeprecation() {
!getOptionValue('--no-deprecation');
}

function deprecateProperty(key, msg, code, isPendingDeprecation) {
const emitDeprecationWarning = getDeprecationWarningEmitter(
code, msg, undefined, false, isPendingDeprecation,
);
return (options) => {
if (key in options) {
emitDeprecationWarning();
}
};
}

// Internal deprecator for pending --pending-deprecation. This can be invoked
// at snapshot building time as the warning permission is only queried at
// run time.
Expand Down Expand Up @@ -947,6 +958,7 @@ module.exports = {
defineReplaceableLazyAttribute,
deprecate,
deprecateInstantiation,
deprecateProperty,
emitExperimentalWarning,
encodingsMap,
exposeInterface,
Expand Down
5 changes: 5 additions & 0 deletions test/parallel/test-http2-client-priority-before-connect.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ if (!common.hasCrypto)
common.skip('missing crypto');
const h2 = require('http2');

common.expectWarning(
'DeprecationWarning',
'http2Stream.priority is longer supported after priority signalling was deprecated in RFC 1993',
'DEP0194');

const server = h2.createServer();

// We use the lower-level API here
Expand Down
1 change: 0 additions & 1 deletion test/parallel/test-http2-client-request-options-errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ const http2 = require('http2');

const optionsToTest = {
endStream: 'boolean',
weight: 'number',
parent: 'number',
exclusive: 'boolean',
silent: 'boolean'
Expand Down
8 changes: 7 additions & 1 deletion test/parallel/test-http2-client-set-priority.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ if (!common.hasCrypto)
const assert = require('assert');
const http2 = require('http2');

common.expectWarning(
'DeprecationWarning',
'Priority signaling has been deprecated as of RFC 1993.',
'DEP0194');

const checkWeight = (actual, expect) => {
const server = http2.createServer();
server.on('stream', common.mustCall((stream, headers, flags) => {
assert.strictEqual(stream.state.weight, expect);
assert.strictEqual(stream.state.sumDependencyWeight, 0);
assert.strictEqual(stream.state.weight, 16);
stream.respond();
stream.end('test');
}));
Expand Down
5 changes: 5 additions & 0 deletions test/parallel/test-http2-priority-cycle-.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ const assert = require('assert');
const http2 = require('http2');
const Countdown = require('../common/countdown');

common.expectWarning(
'DeprecationWarning',
'http2Stream.priority is longer supported after priority signalling was deprecated in RFC 1993',
'DEP0194');

const server = http2.createServer();
const largeBuffer = Buffer.alloc(1e4);

Expand Down
19 changes: 9 additions & 10 deletions test/parallel/test-http2-priority-event.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const h2 = require('http2');

common.expectWarning(
'DeprecationWarning',
'http2Stream.priority is longer supported after priority signalling was deprecated in RFC 1993',
'DEP0194');

const server = h2.createServer();

// We use the lower-level API here
server.on('stream', common.mustCall(onStream));

function onPriority(stream, parent, weight, exclusive) {
assert.strictEqual(stream, 1);
assert.strictEqual(parent, 0);
assert.strictEqual(weight, 1);
assert.strictEqual(exclusive, false);
}

function onStream(stream, headers, flags) {
stream.priority({
parent: 0,
Expand All @@ -33,7 +30,7 @@ function onStream(stream, headers, flags) {

server.listen(0);

server.on('priority', common.mustCall(onPriority));
server.on('priority', common.mustNotCall());

server.on('listening', common.mustCall(() => {

Expand All @@ -48,7 +45,9 @@ server.on('listening', common.mustCall(() => {
});
});

req.on('priority', common.mustCall(onPriority));
// The priority event is not supported anymore by nghttp2
// since 1.65.0.
req.on('priority', common.mustNotCall());

req.on('response', common.mustCall());
req.resume();
Expand Down
5 changes: 5 additions & 0 deletions test/parallel/test-http2-server-stream-session-destroy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ if (!common.hasCrypto)
const assert = require('assert');
const h2 = require('http2');

common.expectWarning(
'DeprecationWarning',
'http2Stream.priority is longer supported after priority signalling was deprecated in RFC 1993',
'DEP0194');

const server = h2.createServer();

server.on('stream', common.mustCall((stream) => {
Expand Down
Loading