diff --git a/doc/api/http2.md b/doc/api/http2.md
index ae143c8bbdd448..0a199fa6dfb30c 100644
--- a/doc/api/http2.md
+++ b/doc/api/http2.md
@@ -84,7 +84,30 @@ Since there are no browsers known that support
[`http2.createSecureServer()`][] is necessary when communicating
with browser clients.
-```js
+```mjs
+import { createSecureServer } from 'node:http2';
+import { readFileSync } from 'node:fs';
+
+const server = createSecureServer({
+ key: readFileSync('localhost-privkey.pem'),
+ cert: readFileSync('localhost-cert.pem'),
+});
+
+server.on('error', (err) => console.error(err));
+
+server.on('stream', (stream, headers) => {
+ // stream is a Duplex
+ stream.respond({
+ 'content-type': 'text/html; charset=utf-8',
+ ':status': 200,
+ });
+ stream.end('
Hello World
');
+});
+
+server.listen(8443);
+```
+
+```cjs
const http2 = require('node:http2');
const fs = require('node:fs');
@@ -117,9 +140,37 @@ openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
The following illustrates an HTTP/2 client:
-```js
+```mjs
+import { connect } from 'node:http2';
+import { readFileSync } from 'node:fs';
+
+const client = connect('https://localhost:8443', {
+ ca: readFileSync('localhost-cert.pem'),
+});
+client.on('error', (err) => console.error(err));
+
+const req = client.request({ ':path': '/' });
+
+req.on('response', (headers, flags) => {
+ for (const name in headers) {
+ console.log(`${name}: ${headers[name]}`);
+ }
+});
+
+req.setEncoding('utf8');
+let data = '';
+req.on('data', (chunk) => { data += chunk; });
+req.on('end', () => {
+ console.log(`\n${data}`);
+ client.close();
+});
+req.end();
+```
+
+```cjs
const http2 = require('node:http2');
const fs = require('node:fs');
+
const client = http2.connect('https://localhost:8443', {
ca: fs.readFileSync('localhost-cert.pem'),
});
@@ -320,7 +371,6 @@ added: v8.4.0
The `'stream'` event is emitted when a new `Http2Stream` is created.
```js
-const http2 = require('node:http2');
session.on('stream', (stream, headers, flags) => {
const method = headers[':method'];
const path = headers[':path'];
@@ -339,7 +389,25 @@ and would instead register a handler for the `'stream'` event emitted by the
`net.Server` or `tls.Server` instances returned by `http2.createServer()` and
`http2.createSecureServer()`, respectively, as in the example below:
-```js
+```mjs
+import { createServer } from 'node:http2';
+
+// Create an unencrypted HTTP/2 server
+const server = createServer();
+
+server.on('stream', (stream, headers) => {
+ stream.respond({
+ 'content-type': 'text/html; charset=utf-8',
+ ':status': 200,
+ });
+ stream.on('error', (error) => console.error(error));
+ stream.end('Hello World
');
+});
+
+server.listen(8000);
+```
+
+```cjs
const http2 = require('node:http2');
// Create an unencrypted HTTP/2 server
@@ -606,7 +674,19 @@ Sets the local endpoint's window size.
The `windowSize` is the total window size to set, not
the delta.
-```js
+```mjs
+import { createServer } from 'node:http2';
+
+const server = createServer();
+const expectedWindowSize = 2 ** 20;
+server.on('session', (session) => {
+
+ // Set local window size to be 2 ** 20
+ session.setLocalWindowSize(expectedWindowSize);
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
@@ -764,7 +844,22 @@ added: v9.4.0
Submits an `ALTSVC` frame (as defined by [RFC 7838][]) to the connected client.
-```js
+```mjs
+import { createServer } from 'node:http2';
+
+const server = createServer();
+server.on('session', (session) => {
+ // Set altsvc for origin https://example.org:80
+ session.altsvc('h2=":8000"', 'https://example.org:80');
+});
+
+server.on('stream', (stream) => {
+ // Set altsvc for a specific stream
+ stream.session.altsvc('h2=":8000"', stream.id);
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
@@ -830,7 +925,20 @@ Submits an `ORIGIN` frame (as defined by [RFC 8336][]) to the connected client
to advertise the set of origins for which the server is capable of providing
authoritative responses.
-```js
+```mjs
+import { createSecureServer } from 'node:http2';
+const options = getSecureOptionsSomehow();
+const server = createSecureServer(options);
+server.on('stream', (stream) => {
+ stream.respond();
+ stream.end('ok');
+});
+server.on('session', (session) => {
+ session.origin('https://example.com', 'https://example.org');
+});
+```
+
+```cjs
const http2 = require('node:http2');
const options = getSecureOptionsSomehow();
const server = http2.createSecureServer(options);
@@ -857,7 +965,18 @@ ASCII origin.
Alternatively, the `origins` option may be used when creating a new HTTP/2
server using the `http2.createSecureServer()` method:
-```js
+```mjs
+import { createSecureServer } from 'node:http2';
+const options = getSecureOptionsSomehow();
+options.origins = ['https://example.com', 'https://example.org'];
+const server = createSecureServer(options);
+server.on('stream', (stream) => {
+ stream.respond();
+ stream.end('ok');
+});
+```
+
+```cjs
const http2 = require('node:http2');
const options = getSecureOptionsSomehow();
options.origins = ['https://example.com', 'https://example.org'];
@@ -891,7 +1010,18 @@ the client. The event is emitted with the `ALTSVC` value, origin, and stream
ID. If no `origin` is provided in the `ALTSVC` frame, `origin` will
be an empty string.
-```js
+```mjs
+import { connect } from 'node:http2';
+const client = connect('https://example.org');
+
+client.on('altsvc', (alt, origin, streamId) => {
+ console.log(alt);
+ console.log(origin);
+ console.log(streamId);
+});
+```
+
+```cjs
const http2 = require('node:http2');
const client = http2.connect('https://example.org');
@@ -915,7 +1045,17 @@ the client. The event is emitted with an array of `origin` strings. The
`http2session.originSet` will be updated to include the received
origins.
-```js
+```mjs
+import { connect } from 'node:http2';
+const client = connect('https://example.org');
+
+client.on('origin', (origins) => {
+ for (let n = 0; n < origins.length; n++)
+ console.log(origins[n]);
+});
+```
+
+```cjs
const http2 = require('node:http2');
const client = http2.connect('https://example.org');
@@ -968,7 +1108,23 @@ If the `session` is closed before the actual request be executed, an
This method is only available if `http2session.type` is equal to
`http2.constants.NGHTTP2_SESSION_CLIENT`.
-```js
+```mjs
+import { connect, constants } from 'node:http2';
+const clientSession = connect('https://localhost:1234');
+const {
+ HTTP2_HEADER_PATH,
+ HTTP2_HEADER_STATUS,
+} = constants;
+
+const req = clientSession.request({ [HTTP2_HEADER_PATH]: '/' });
+req.on('response', (headers) => {
+ console.log(headers[HTTP2_HEADER_STATUS]);
+ req.on('data', (chunk) => { /* .. */ });
+ req.on('end', () => { /* .. */ });
+});
+```
+
+```cjs
const http2 = require('node:http2');
const clientSession = http2.connect('https://localhost:1234');
const {
@@ -1388,7 +1544,17 @@ changes:
* `msecs` {number}
* `callback` {Function}
-```js
+```mjs
+import { connect, constants } from 'node:http2';
+const client = connect('http://example.org:8000');
+const { NGHTTP2_CANCEL } = constants;
+const req = client.request({ ':path': '/' });
+
+// Cancel the stream if there's no activity after 5 seconds
+req.setTimeout(5000, () => req.close(NGHTTP2_CANCEL));
+```
+
+```cjs
const http2 = require('node:http2');
const client = http2.connect('http://example.org:8000');
const { NGHTTP2_CANCEL } = http2.constants;
@@ -1437,7 +1603,19 @@ request or sending a response, the `options.waitForTrailers` option must be set
in order to keep the `Http2Stream` open after the final `DATA` frame so that
trailers can be sent.
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer();
+server.on('stream', (stream) => {
+ stream.respond(undefined, { waitForTrailers: true });
+ stream.on('wantTrailers', () => {
+ stream.sendTrailers({ xyz: 'abc' });
+ });
+ stream.end('Hello World');
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
@@ -1528,7 +1706,16 @@ received for this stream from the connected HTTP/2 server. The listener is
invoked with two arguments: an `Object` containing the received
[HTTP/2 Headers Object][], and flags associated with the headers.
-```js
+```mjs
+import { connect } from 'node:http2';
+const client = connect('https://localhost');
+const req = client.request({ ':path': '/' });
+req.on('response', (headers, flags) => {
+ console.log(headers[':status']);
+});
+```
+
+```cjs
const http2 = require('node:http2');
const client = http2.connect('https://localhost');
const req = client.request({ ':path': '/' });
@@ -1614,7 +1801,21 @@ Initiates a push stream. The callback is invoked with the new `Http2Stream`
instance created for the push stream passed as the second argument, or an
`Error` passed as the first argument.
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer();
+server.on('stream', (stream) => {
+ stream.respond({ ':status': 200 });
+ stream.pushStream({ ':path': '/' }, (err, pushStream, headers) => {
+ if (err) throw err;
+ pushStream.respond({ ':status': 200 });
+ pushStream.end('some pushed data');
+ });
+ stream.end('some data');
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
@@ -1654,7 +1855,16 @@ changes:
* `waitForTrailers` {boolean} When `true`, the `Http2Stream` will emit the
`'wantTrailers'` event after the final `DATA` frame has been sent.
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer();
+server.on('stream', (stream) => {
+ stream.respond({ ':status': 200 });
+ stream.end('some data');
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
@@ -1673,7 +1883,19 @@ close when the final `DATA` frame is transmitted. User code must call either
`http2stream.sendTrailers()` or `http2stream.close()` to close the
`Http2Stream`.
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer();
+server.on('stream', (stream) => {
+ stream.respond({ ':status': 200 }, { waitForTrailers: true });
+ stream.on('wantTrailers', () => {
+ stream.sendTrailers({ ABC: 'some value to send' });
+ });
+ stream.end('some data');
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
@@ -1721,7 +1943,26 @@ closed using an `RST_STREAM` frame using the standard `INTERNAL_ERROR` code.
When used, the `Http2Stream` object's `Duplex` interface will be closed
automatically.
-```js
+```mjs
+import { createServer } from 'node:http2';
+import { openSync, fstatSync, closeSync } from 'node:fs';
+
+const server = createServer();
+server.on('stream', (stream) => {
+ const fd = openSync('/some/file', 'r');
+
+ const stat = fstatSync(fd);
+ const headers = {
+ 'content-length': stat.size,
+ 'last-modified': stat.mtime.toUTCString(),
+ 'content-type': 'text/plain; charset=utf-8',
+ };
+ stream.respondWithFD(fd, headers);
+ stream.on('close', () => closeSync(fd));
+});
+```
+
+```cjs
const http2 = require('node:http2');
const fs = require('node:fs');
@@ -1766,7 +2007,30 @@ close when the final `DATA` frame is transmitted. User code _must_ call either
`http2stream.sendTrailers()` or `http2stream.close()` to close the
`Http2Stream`.
-```js
+```mjs
+import { createServer } from 'node:http2';
+import { openSync, fstatSync, closeSync } from 'node:fs';
+
+const server = createServer();
+server.on('stream', (stream) => {
+ const fd = openSync('/some/file', 'r');
+
+ const stat = fstatSync(fd);
+ const headers = {
+ 'content-length': stat.size,
+ 'last-modified': stat.mtime.toUTCString(),
+ 'content-type': 'text/plain; charset=utf-8',
+ };
+ stream.respondWithFD(fd, headers, { waitForTrailers: true });
+ stream.on('wantTrailers', () => {
+ stream.sendTrailers({ ABC: 'some value to send' });
+ });
+
+ stream.on('close', () => closeSync(fd));
+});
+```
+
+```cjs
const http2 = require('node:http2');
const fs = require('node:fs');
@@ -1833,7 +2097,37 @@ the stream will be destroyed.
Example using a file path:
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer();
+server.on('stream', (stream) => {
+ function statCheck(stat, headers) {
+ headers['last-modified'] = stat.mtime.toUTCString();
+ }
+
+ function onError(err) {
+ // stream.respond() can throw if the stream has been destroyed by
+ // the other side.
+ try {
+ if (err.code === 'ENOENT') {
+ stream.respond({ ':status': 404 });
+ } else {
+ stream.respond({ ':status': 500 });
+ }
+ } catch (err) {
+ // Perform actual error handling.
+ console.error(err);
+ }
+ stream.end();
+ }
+
+ stream.respondWithFile('/some/file',
+ { 'content-type': 'text/plain; charset=utf-8' },
+ { statCheck, onError });
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
@@ -1868,7 +2162,22 @@ by returning `false`. For instance, a conditional request may check the stat
results to determine if the file has been modified to return an appropriate
`304` response:
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer();
+server.on('stream', (stream) => {
+ function statCheck(stat, headers) {
+ // Check the stat here...
+ stream.respond({ ':status': 304 });
+ return false; // Cancel the send operation
+ }
+ stream.respondWithFile('/some/file',
+ { 'content-type': 'text/plain; charset=utf-8' },
+ { statCheck });
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
@@ -1903,7 +2212,20 @@ close when the final `DATA` frame is transmitted. User code must call either
`http2stream.sendTrailers()` or `http2stream.close()` to close the
`Http2Stream`.
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer();
+server.on('stream', (stream) => {
+ stream.respondWithFile('/some/file',
+ { 'content-type': 'text/plain; charset=utf-8' },
+ { waitForTrailers: true });
+ stream.on('wantTrailers', () => {
+ stream.sendTrailers({ ABC: 'some value to send' });
+ });
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream) => {
@@ -2016,9 +2338,32 @@ added: v8.4.0
The `'stream'` event is emitted when a `'stream'` event has been emitted by
an `Http2Session` associated with the server.
-See also [`Http2Session`'s `'stream'` event][].
+See also [`Http2Session`'s `'stream'` event][].
+
+```mjs
+import { createServer, constants } from 'node:http2';
+const {
+ HTTP2_HEADER_METHOD,
+ HTTP2_HEADER_PATH,
+ HTTP2_HEADER_STATUS,
+ HTTP2_HEADER_CONTENT_TYPE,
+} = constants;
+
+const server = createServer();
+server.on('stream', (stream, headers, flags) => {
+ const method = headers[HTTP2_HEADER_METHOD];
+ const path = headers[HTTP2_HEADER_PATH];
+ // ...
+ stream.respond({
+ [HTTP2_HEADER_STATUS]: 200,
+ [HTTP2_HEADER_CONTENT_TYPE]: 'text/plain; charset=utf-8',
+ });
+ stream.write('hello ');
+ stream.end('world');
+});
+```
-```js
+```cjs
const http2 = require('node:http2');
const {
HTTP2_HEADER_METHOD,
@@ -2249,7 +2594,32 @@ an `Http2Session` associated with the server.
See also [`Http2Session`'s `'stream'` event][].
-```js
+```mjs
+import { createSecureServer, constants } from 'node:http2';
+const {
+ HTTP2_HEADER_METHOD,
+ HTTP2_HEADER_PATH,
+ HTTP2_HEADER_STATUS,
+ HTTP2_HEADER_CONTENT_TYPE,
+} = constants;
+
+const options = getOptionsSomehow();
+
+const server = createSecureServer(options);
+server.on('stream', (stream, headers, flags) => {
+ const method = headers[HTTP2_HEADER_METHOD];
+ const path = headers[HTTP2_HEADER_PATH];
+ // ...
+ stream.respond({
+ [HTTP2_HEADER_STATUS]: 200,
+ [HTTP2_HEADER_CONTENT_TYPE]: 'text/plain; charset=utf-8',
+ });
+ stream.write('hello ');
+ stream.end('world');
+});
+```
+
+```cjs
const http2 = require('node:http2');
const {
HTTP2_HEADER_METHOD,
@@ -2533,7 +2903,27 @@ Since there are no browsers known that support
[`http2.createSecureServer()`][] is necessary when communicating
with browser clients.
-```js
+```mjs
+import { createServer } from 'node:http2';
+
+// Create an unencrypted HTTP/2 server.
+// Since there are no browsers known that support
+// unencrypted HTTP/2, the use of `createSecureServer()`
+// is necessary when communicating with browser clients.
+const server = createServer();
+
+server.on('stream', (stream, headers) => {
+ stream.respond({
+ 'content-type': 'text/html; charset=utf-8',
+ ':status': 200,
+ });
+ stream.end('Hello World
');
+});
+
+server.listen(8000);
+```
+
+```cjs
const http2 = require('node:http2');
// Create an unencrypted HTTP/2 server.
@@ -2675,7 +3065,30 @@ changes:
Returns a `tls.Server` instance that creates and manages `Http2Session`
instances.
-```js
+```mjs
+import { createSecureServer } from 'node:http2';
+import { readFileSync } from 'node:fs';
+
+const options = {
+ key: readFileSync('server-key.pem'),
+ cert: readFileSync('server-cert.pem'),
+};
+
+// Create a secure HTTP/2 server
+const server = createSecureServer(options);
+
+server.on('stream', (stream, headers) => {
+ stream.respond({
+ 'content-type': 'text/html; charset=utf-8',
+ ':status': 200,
+ });
+ stream.end('Hello World
');
+});
+
+server.listen(8443);
+```
+
+```cjs
const http2 = require('node:http2');
const fs = require('node:fs');
@@ -2807,7 +3220,16 @@ changes:
Returns a `ClientHttp2Session` instance.
-```js
+```mjs
+import { connect } from 'node:http2';
+const client = connect('https://localhost:1234');
+
+/* Use the client */
+
+client.close();
+```
+
+```cjs
const http2 = require('node:http2');
const client = http2.connect('https://localhost:1234');
@@ -2869,7 +3291,16 @@ Returns a `Buffer` instance containing serialized representation of the given
HTTP/2 settings as specified in the [HTTP/2][] specification. This is intended
for use with the `HTTP2-Settings` header field.
-```js
+```mjs
+import { getPackedSettings } from 'node:http2';
+
+const packed = getPackedSettings({ enablePush: false });
+
+console.log(packed.toString('base64'));
+// Prints: AAIAAAAA
+```
+
+```cjs
const http2 = require('node:http2');
const packed = http2.getPackedSettings({ enablePush: false });
@@ -2958,7 +3389,16 @@ For incoming headers:
* For duplicate `cookie` headers, the values are joined together with '; '.
* For all other headers, the values are joined together with ', '.
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer();
+server.on('stream', (stream, headers) => {
+ console.log(headers[':path']);
+ console.log(headers.ABC);
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer();
server.on('stream', (stream, headers) => {
@@ -3106,7 +3546,22 @@ characters, per the requirements of the HTTP specification.
To receive pushed streams on the client, set a listener for the `'stream'`
event on the `ClientHttp2Session`:
-```js
+```mjs
+import { connect } from 'node:http2';
+
+const client = connect('http://localhost');
+
+client.on('stream', (pushedStream, requestHeaders) => {
+ pushedStream.on('push', (responseHeaders) => {
+ // Process response headers
+ });
+ pushedStream.on('data', (chunk) => { /* handle pushed data */ });
+});
+
+const req = client.request({ ':path': '/' });
+```
+
+```cjs
const http2 = require('node:http2');
const client = http2.connect('http://localhost');
@@ -3128,7 +3583,20 @@ for TCP/IP connections.
A simple TCP Server:
-```js
+```mjs
+import { createServer } from 'node:net';
+
+const server = createServer((socket) => {
+ let name = '';
+ socket.setEncoding('utf8');
+ socket.on('data', (chunk) => name += chunk);
+ socket.on('end', () => socket.end(`hello ${name}`));
+});
+
+server.listen(8000);
+```
+
+```cjs
const net = require('node:net');
const server = net.createServer((socket) => {
@@ -3143,7 +3611,35 @@ server.listen(8000);
An HTTP/2 CONNECT proxy:
-```js
+```mjs
+import { createServer, constants } from 'node:http2';
+const { NGHTTP2_REFUSED_STREAM, NGHTTP2_CONNECT_ERROR } = constants;
+import { connect } from 'node:net';
+
+const proxy = createServer();
+proxy.on('stream', (stream, headers) => {
+ if (headers[':method'] !== 'CONNECT') {
+ // Only accept CONNECT requests
+ stream.close(NGHTTP2_REFUSED_STREAM);
+ return;
+ }
+ const auth = new URL(`tcp://${headers[':authority']}`);
+ // It's a very good idea to verify that hostname and port are
+ // things this proxy should be connecting to.
+ const socket = connect(auth.port, auth.hostname, () => {
+ stream.respond();
+ socket.pipe(stream);
+ stream.pipe(socket);
+ });
+ socket.on('error', (error) => {
+ stream.close(NGHTTP2_CONNECT_ERROR);
+ });
+});
+
+proxy.listen(8001);
+```
+
+```cjs
const http2 = require('node:http2');
const { NGHTTP2_REFUSED_STREAM } = http2.constants;
const net = require('node:net');
@@ -3173,7 +3669,32 @@ proxy.listen(8001);
An HTTP/2 CONNECT client:
-```js
+```mjs
+import { connect, constants } from 'node:http2';
+
+const client = connect('http://localhost:8001');
+
+// Must not specify the ':path' and ':scheme' headers
+// for CONNECT requests or an error will be thrown.
+const req = client.request({
+ ':method': 'CONNECT',
+ ':authority': 'localhost:8000',
+});
+
+req.on('response', (headers) => {
+ console.log(headers[constants.HTTP2_HEADER_STATUS]);
+});
+let data = '';
+req.setEncoding('utf8');
+req.on('data', (chunk) => data += chunk);
+req.on('end', () => {
+ console.log(`The server says: ${data}`);
+ client.close();
+});
+req.end('Jane');
+```
+
+```cjs
const http2 = require('node:http2');
const client = http2.connect('http://localhost:8001');
@@ -3207,7 +3728,13 @@ method as a tunnel for other communication protocols (such as WebSockets).
The use of the Extended CONNECT Protocol is enabled by HTTP/2 servers by using
the `enableConnectProtocol` setting:
-```js
+```mjs
+import { createServer } from 'node:http2';
+const settings = { enableConnectProtocol: true };
+const server = createServer({ settings });
+```
+
+```cjs
const http2 = require('node:http2');
const settings = { enableConnectProtocol: true };
const server = http2.createServer({ settings });
@@ -3217,7 +3744,18 @@ Once the client receives the `SETTINGS` frame from the server indicating that
the extended CONNECT may be used, it may send `CONNECT` requests that use the
`':protocol'` HTTP/2 pseudo-header:
-```js
+```mjs
+import { connect } from 'node:http2';
+const client = connect('http://localhost:8080');
+client.on('remoteSettings', (settings) => {
+ if (settings.enableConnectProtocol) {
+ const req = client.request({ ':method': 'CONNECT', ':protocol': 'foo' });
+ // ...
+ }
+});
+```
+
+```cjs
const http2 = require('node:http2');
const client = http2.connect('http://localhost:8080');
client.on('remoteSettings', (settings) => {
@@ -3240,7 +3778,17 @@ different implementation.
The following example creates an HTTP/2 server using the compatibility
API:
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer((req, res) => {
+ res.setHeader('Content-Type', 'text/html');
+ res.setHeader('X-Foo', 'bar');
+ res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
+ res.end('ok');
+});
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
@@ -3269,7 +3817,31 @@ features of HTTP/2.
The following example creates a server that supports both protocols:
-```js
+```mjs
+import { createSecureServer } from 'node:http2';
+import { readFileSync } from 'node:fs';
+
+const cert = readFileSync('./cert.pem');
+const key = readFileSync('./key.pem');
+
+const server = createSecureServer(
+ { cert, key, allowHTTP1: true },
+ onRequest,
+).listen(8000);
+
+function onRequest(req, res) {
+ // Detects if it is a HTTPS request or HTTP/2
+ const { socket: { alpnProtocol } } = req.httpVersion === '2.0' ?
+ req.stream.session : req;
+ res.writeHead(200, { 'content-type': 'application/json' });
+ res.end(JSON.stringify({
+ alpnProtocol,
+ httpVersion: req.httpVersion,
+ }));
+}
+```
+
+```cjs
const { createSecureServer } = require('node:http2');
const { readFileSync } = require('node:fs');
@@ -3983,7 +4555,16 @@ more information.
All other interactions will be routed directly to the socket.
-```js
+```mjs
+import { createServer } from 'node:http2';
+const server = createServer((req, res) => {
+ const ip = req.socket.remoteAddress;
+ const port = req.socket.remotePort;
+ res.end(`Your IP address is ${ip} and your source port is ${port}.`);
+}).listen(3000);
+```
+
+```cjs
const http2 = require('node:http2');
const server = http2.createServer((req, res) => {
const ip = req.socket.remoteAddress;
@@ -4194,7 +4775,22 @@ will result in a [`TypeError`][] being thrown.
The [Performance Observer][] API can be used to collect basic performance
metrics for each `Http2Session` and `Http2Stream` instance.
-```js
+```mjs
+import { PerformanceObserver } from 'node:perf_hooks';
+
+const obs = new PerformanceObserver((items) => {
+ const entry = items.getEntries()[0];
+ console.log(entry.entryType); // prints 'http2'
+ if (entry.name === 'Http2Session') {
+ // Entry contains statistics about the Http2Session
+ } else if (entry.name === 'Http2Stream') {
+ // Entry contains statistics about the Http2Stream
+ }
+});
+obs.observe({ entryTypes: ['http2'] });
+```
+
+```cjs
const { PerformanceObserver } = require('node:perf_hooks');
const obs = new PerformanceObserver((items) => {