Skip to content

Commit 7e25fab

Browse files
mfdebiantargos
authored andcommittedOct 2, 2024
doc: add esm examples to node:http2
PR-URL: #54292 Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 0843077 commit 7e25fab

File tree

1 file changed

+636
-40
lines changed

1 file changed

+636
-40
lines changed
 

‎doc/api/http2.md

+636-40
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,30 @@ Since there are no browsers known that support
8484
[`http2.createSecureServer()`][] is necessary when communicating
8585
with browser clients.
8686

87-
```js
87+
```mjs
88+
import { createSecureServer } from 'node:http2';
89+
import { readFileSync } from 'node:fs';
90+
91+
const server = createSecureServer({
92+
key: readFileSync('localhost-privkey.pem'),
93+
cert: readFileSync('localhost-cert.pem'),
94+
});
95+
96+
server.on('error', (err) => console.error(err));
97+
98+
server.on('stream', (stream, headers) => {
99+
// stream is a Duplex
100+
stream.respond({
101+
'content-type': 'text/html; charset=utf-8',
102+
':status': 200,
103+
});
104+
stream.end('<h1>Hello World</h1>');
105+
});
106+
107+
server.listen(8443);
108+
```
109+
110+
```cjs
88111
const http2 = require('node:http2');
89112
const fs = require('node:fs');
90113

@@ -117,9 +140,37 @@ openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
117140

118141
The following illustrates an HTTP/2 client:
119142

120-
```js
143+
```mjs
144+
import { connect } from 'node:http2';
145+
import { readFileSync } from 'node:fs';
146+
147+
const client = connect('https://localhost:8443', {
148+
ca: readFileSync('localhost-cert.pem'),
149+
});
150+
client.on('error', (err) => console.error(err));
151+
152+
const req = client.request({ ':path': '/' });
153+
154+
req.on('response', (headers, flags) => {
155+
for (const name in headers) {
156+
console.log(`${name}: ${headers[name]}`);
157+
}
158+
});
159+
160+
req.setEncoding('utf8');
161+
let data = '';
162+
req.on('data', (chunk) => { data += chunk; });
163+
req.on('end', () => {
164+
console.log(`\n${data}`);
165+
client.close();
166+
});
167+
req.end();
168+
```
169+
170+
```cjs
121171
const http2 = require('node:http2');
122172
const fs = require('node:fs');
173+
123174
const client = http2.connect('https://localhost:8443', {
124175
ca: fs.readFileSync('localhost-cert.pem'),
125176
});
@@ -320,7 +371,6 @@ added: v8.4.0
320371
The `'stream'` event is emitted when a new `Http2Stream` is created.
321372

322373
```js
323-
const http2 = require('node:http2');
324374
session.on('stream', (stream, headers, flags) => {
325375
const method = headers[':method'];
326376
const path = headers[':path'];
@@ -339,7 +389,25 @@ and would instead register a handler for the `'stream'` event emitted by the
339389
`net.Server` or `tls.Server` instances returned by `http2.createServer()` and
340390
`http2.createSecureServer()`, respectively, as in the example below:
341391

342-
```js
392+
```mjs
393+
import { createServer } from 'node:http2';
394+
395+
// Create an unencrypted HTTP/2 server
396+
const server = createServer();
397+
398+
server.on('stream', (stream, headers) => {
399+
stream.respond({
400+
'content-type': 'text/html; charset=utf-8',
401+
':status': 200,
402+
});
403+
stream.on('error', (error) => console.error(error));
404+
stream.end('<h1>Hello World</h1>');
405+
});
406+
407+
server.listen(8000);
408+
```
409+
410+
```cjs
343411
const http2 = require('node:http2');
344412

345413
// Create an unencrypted HTTP/2 server
@@ -606,7 +674,19 @@ Sets the local endpoint's window size.
606674
The `windowSize` is the total window size to set, not
607675
the delta.
608676

609-
```js
677+
```mjs
678+
import { createServer } from 'node:http2';
679+
680+
const server = createServer();
681+
const expectedWindowSize = 2 ** 20;
682+
server.on('session', (session) => {
683+
684+
// Set local window size to be 2 ** 20
685+
session.setLocalWindowSize(expectedWindowSize);
686+
});
687+
```
688+
689+
```cjs
610690
const http2 = require('node:http2');
611691

612692
const server = http2.createServer();
@@ -764,7 +844,22 @@ added: v9.4.0
764844

765845
Submits an `ALTSVC` frame (as defined by [RFC 7838][]) to the connected client.
766846

767-
```js
847+
```mjs
848+
import { createServer } from 'node:http2';
849+
850+
const server = createServer();
851+
server.on('session', (session) => {
852+
// Set altsvc for origin https://example.org:80
853+
session.altsvc('h2=":8000"', 'https://example.org:80');
854+
});
855+
856+
server.on('stream', (stream) => {
857+
// Set altsvc for a specific stream
858+
stream.session.altsvc('h2=":8000"', stream.id);
859+
});
860+
```
861+
862+
```cjs
768863
const http2 = require('node:http2');
769864

770865
const server = http2.createServer();
@@ -830,7 +925,20 @@ Submits an `ORIGIN` frame (as defined by [RFC 8336][]) to the connected client
830925
to advertise the set of origins for which the server is capable of providing
831926
authoritative responses.
832927

833-
```js
928+
```mjs
929+
import { createSecureServer } from 'node:http2';
930+
const options = getSecureOptionsSomehow();
931+
const server = createSecureServer(options);
932+
server.on('stream', (stream) => {
933+
stream.respond();
934+
stream.end('ok');
935+
});
936+
server.on('session', (session) => {
937+
session.origin('https://example.com', 'https://example.org');
938+
});
939+
```
940+
941+
```cjs
834942
const http2 = require('node:http2');
835943
const options = getSecureOptionsSomehow();
836944
const server = http2.createSecureServer(options);
@@ -857,7 +965,18 @@ ASCII origin.
857965
Alternatively, the `origins` option may be used when creating a new HTTP/2
858966
server using the `http2.createSecureServer()` method:
859967

860-
```js
968+
```mjs
969+
import { createSecureServer } from 'node:http2';
970+
const options = getSecureOptionsSomehow();
971+
options.origins = ['https://example.com', 'https://example.org'];
972+
const server = createSecureServer(options);
973+
server.on('stream', (stream) => {
974+
stream.respond();
975+
stream.end('ok');
976+
});
977+
```
978+
979+
```cjs
861980
const http2 = require('node:http2');
862981
const options = getSecureOptionsSomehow();
863982
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
8911010
ID. If no `origin` is provided in the `ALTSVC` frame, `origin` will
8921011
be an empty string.
8931012

894-
```js
1013+
```mjs
1014+
import { connect } from 'node:http2';
1015+
const client = connect('https://example.org');
1016+
1017+
client.on('altsvc', (alt, origin, streamId) => {
1018+
console.log(alt);
1019+
console.log(origin);
1020+
console.log(streamId);
1021+
});
1022+
```
1023+
1024+
```cjs
8951025
const http2 = require('node:http2');
8961026
const client = http2.connect('https://example.org');
8971027

@@ -915,7 +1045,17 @@ the client. The event is emitted with an array of `origin` strings. The
9151045
`http2session.originSet` will be updated to include the received
9161046
origins.
9171047

918-
```js
1048+
```mjs
1049+
import { connect } from 'node:http2';
1050+
const client = connect('https://example.org');
1051+
1052+
client.on('origin', (origins) => {
1053+
for (let n = 0; n < origins.length; n++)
1054+
console.log(origins[n]);
1055+
});
1056+
```
1057+
1058+
```cjs
9191059
const http2 = require('node:http2');
9201060
const client = http2.connect('https://example.org');
9211061

@@ -968,7 +1108,23 @@ If the `session` is closed before the actual request be executed, an
9681108
This method is only available if `http2session.type` is equal to
9691109
`http2.constants.NGHTTP2_SESSION_CLIENT`.
9701110

971-
```js
1111+
```mjs
1112+
import { connect, constants } from 'node:http2';
1113+
const clientSession = connect('https://localhost:1234');
1114+
const {
1115+
HTTP2_HEADER_PATH,
1116+
HTTP2_HEADER_STATUS,
1117+
} = constants;
1118+
1119+
const req = clientSession.request({ [HTTP2_HEADER_PATH]: '/' });
1120+
req.on('response', (headers) => {
1121+
console.log(headers[HTTP2_HEADER_STATUS]);
1122+
req.on('data', (chunk) => { /* .. */ });
1123+
req.on('end', () => { /* .. */ });
1124+
});
1125+
```
1126+
1127+
```cjs
9721128
const http2 = require('node:http2');
9731129
const clientSession = http2.connect('https://localhost:1234');
9741130
const {
@@ -1388,7 +1544,17 @@ changes:
13881544
* `msecs` {number}
13891545
* `callback` {Function}
13901546

1391-
```js
1547+
```mjs
1548+
import { connect, constants } from 'node:http2';
1549+
const client = connect('http://example.org:8000');
1550+
const { NGHTTP2_CANCEL } = constants;
1551+
const req = client.request({ ':path': '/' });
1552+
1553+
// Cancel the stream if there's no activity after 5 seconds
1554+
req.setTimeout(5000, () => req.close(NGHTTP2_CANCEL));
1555+
```
1556+
1557+
```cjs
13921558
const http2 = require('node:http2');
13931559
const client = http2.connect('http://example.org:8000');
13941560
const { NGHTTP2_CANCEL } = http2.constants;
@@ -1437,7 +1603,19 @@ request or sending a response, the `options.waitForTrailers` option must be set
14371603
in order to keep the `Http2Stream` open after the final `DATA` frame so that
14381604
trailers can be sent.
14391605

1440-
```js
1606+
```mjs
1607+
import { createServer } from 'node:http2';
1608+
const server = createServer();
1609+
server.on('stream', (stream) => {
1610+
stream.respond(undefined, { waitForTrailers: true });
1611+
stream.on('wantTrailers', () => {
1612+
stream.sendTrailers({ xyz: 'abc' });
1613+
});
1614+
stream.end('Hello World');
1615+
});
1616+
```
1617+
1618+
```cjs
14411619
const http2 = require('node:http2');
14421620
const server = http2.createServer();
14431621
server.on('stream', (stream) => {
@@ -1528,7 +1706,16 @@ received for this stream from the connected HTTP/2 server. The listener is
15281706
invoked with two arguments: an `Object` containing the received
15291707
[HTTP/2 Headers Object][], and flags associated with the headers.
15301708

1531-
```js
1709+
```mjs
1710+
import { connect } from 'node:http2';
1711+
const client = connect('https://localhost');
1712+
const req = client.request({ ':path': '/' });
1713+
req.on('response', (headers, flags) => {
1714+
console.log(headers[':status']);
1715+
});
1716+
```
1717+
1718+
```cjs
15321719
const http2 = require('node:http2');
15331720
const client = http2.connect('https://localhost');
15341721
const req = client.request({ ':path': '/' });
@@ -1614,7 +1801,21 @@ Initiates a push stream. The callback is invoked with the new `Http2Stream`
16141801
instance created for the push stream passed as the second argument, or an
16151802
`Error` passed as the first argument.
16161803

1617-
```js
1804+
```mjs
1805+
import { createServer } from 'node:http2';
1806+
const server = createServer();
1807+
server.on('stream', (stream) => {
1808+
stream.respond({ ':status': 200 });
1809+
stream.pushStream({ ':path': '/' }, (err, pushStream, headers) => {
1810+
if (err) throw err;
1811+
pushStream.respond({ ':status': 200 });
1812+
pushStream.end('some pushed data');
1813+
});
1814+
stream.end('some data');
1815+
});
1816+
```
1817+
1818+
```cjs
16181819
const http2 = require('node:http2');
16191820
const server = http2.createServer();
16201821
server.on('stream', (stream) => {
@@ -1654,7 +1855,16 @@ changes:
16541855
* `waitForTrailers` {boolean} When `true`, the `Http2Stream` will emit the
16551856
`'wantTrailers'` event after the final `DATA` frame has been sent.
16561857

1657-
```js
1858+
```mjs
1859+
import { createServer } from 'node:http2';
1860+
const server = createServer();
1861+
server.on('stream', (stream) => {
1862+
stream.respond({ ':status': 200 });
1863+
stream.end('some data');
1864+
});
1865+
```
1866+
1867+
```cjs
16581868
const http2 = require('node:http2');
16591869
const server = http2.createServer();
16601870
server.on('stream', (stream) => {
@@ -1673,7 +1883,19 @@ close when the final `DATA` frame is transmitted. User code must call either
16731883
`http2stream.sendTrailers()` or `http2stream.close()` to close the
16741884
`Http2Stream`.
16751885

1676-
```js
1886+
```mjs
1887+
import { createServer } from 'node:http2';
1888+
const server = createServer();
1889+
server.on('stream', (stream) => {
1890+
stream.respond({ ':status': 200 }, { waitForTrailers: true });
1891+
stream.on('wantTrailers', () => {
1892+
stream.sendTrailers({ ABC: 'some value to send' });
1893+
});
1894+
stream.end('some data');
1895+
});
1896+
```
1897+
1898+
```cjs
16771899
const http2 = require('node:http2');
16781900
const server = http2.createServer();
16791901
server.on('stream', (stream) => {
@@ -1721,7 +1943,26 @@ closed using an `RST_STREAM` frame using the standard `INTERNAL_ERROR` code.
17211943
When used, the `Http2Stream` object's `Duplex` interface will be closed
17221944
automatically.
17231945

1724-
```js
1946+
```mjs
1947+
import { createServer } from 'node:http2';
1948+
import { openSync, fstatSync, closeSync } from 'node:fs';
1949+
1950+
const server = createServer();
1951+
server.on('stream', (stream) => {
1952+
const fd = openSync('/some/file', 'r');
1953+
1954+
const stat = fstatSync(fd);
1955+
const headers = {
1956+
'content-length': stat.size,
1957+
'last-modified': stat.mtime.toUTCString(),
1958+
'content-type': 'text/plain; charset=utf-8',
1959+
};
1960+
stream.respondWithFD(fd, headers);
1961+
stream.on('close', () => closeSync(fd));
1962+
});
1963+
```
1964+
1965+
```cjs
17251966
const http2 = require('node:http2');
17261967
const fs = require('node:fs');
17271968

@@ -1766,7 +2007,30 @@ close when the final `DATA` frame is transmitted. User code _must_ call either
17662007
`http2stream.sendTrailers()` or `http2stream.close()` to close the
17672008
`Http2Stream`.
17682009

1769-
```js
2010+
```mjs
2011+
import { createServer } from 'node:http2';
2012+
import { openSync, fstatSync, closeSync } from 'node:fs';
2013+
2014+
const server = createServer();
2015+
server.on('stream', (stream) => {
2016+
const fd = openSync('/some/file', 'r');
2017+
2018+
const stat = fstatSync(fd);
2019+
const headers = {
2020+
'content-length': stat.size,
2021+
'last-modified': stat.mtime.toUTCString(),
2022+
'content-type': 'text/plain; charset=utf-8',
2023+
};
2024+
stream.respondWithFD(fd, headers, { waitForTrailers: true });
2025+
stream.on('wantTrailers', () => {
2026+
stream.sendTrailers({ ABC: 'some value to send' });
2027+
});
2028+
2029+
stream.on('close', () => closeSync(fd));
2030+
});
2031+
```
2032+
2033+
```cjs
17702034
const http2 = require('node:http2');
17712035
const fs = require('node:fs');
17722036

@@ -1833,7 +2097,37 @@ the stream will be destroyed.
18332097

18342098
Example using a file path:
18352099

1836-
```js
2100+
```mjs
2101+
import { createServer } from 'node:http2';
2102+
const server = createServer();
2103+
server.on('stream', (stream) => {
2104+
function statCheck(stat, headers) {
2105+
headers['last-modified'] = stat.mtime.toUTCString();
2106+
}
2107+
2108+
function onError(err) {
2109+
// stream.respond() can throw if the stream has been destroyed by
2110+
// the other side.
2111+
try {
2112+
if (err.code === 'ENOENT') {
2113+
stream.respond({ ':status': 404 });
2114+
} else {
2115+
stream.respond({ ':status': 500 });
2116+
}
2117+
} catch (err) {
2118+
// Perform actual error handling.
2119+
console.error(err);
2120+
}
2121+
stream.end();
2122+
}
2123+
2124+
stream.respondWithFile('/some/file',
2125+
{ 'content-type': 'text/plain; charset=utf-8' },
2126+
{ statCheck, onError });
2127+
});
2128+
```
2129+
2130+
```cjs
18372131
const http2 = require('node:http2');
18382132
const server = http2.createServer();
18392133
server.on('stream', (stream) => {
@@ -1868,7 +2162,22 @@ by returning `false`. For instance, a conditional request may check the stat
18682162
results to determine if the file has been modified to return an appropriate
18692163
`304` response:
18702164

1871-
```js
2165+
```mjs
2166+
import { createServer } from 'node:http2';
2167+
const server = createServer();
2168+
server.on('stream', (stream) => {
2169+
function statCheck(stat, headers) {
2170+
// Check the stat here...
2171+
stream.respond({ ':status': 304 });
2172+
return false; // Cancel the send operation
2173+
}
2174+
stream.respondWithFile('/some/file',
2175+
{ 'content-type': 'text/plain; charset=utf-8' },
2176+
{ statCheck });
2177+
});
2178+
```
2179+
2180+
```cjs
18722181
const http2 = require('node:http2');
18732182
const server = http2.createServer();
18742183
server.on('stream', (stream) => {
@@ -1903,7 +2212,20 @@ close when the final `DATA` frame is transmitted. User code must call either
19032212
`http2stream.sendTrailers()` or `http2stream.close()` to close the
19042213
`Http2Stream`.
19052214

1906-
```js
2215+
```mjs
2216+
import { createServer } from 'node:http2';
2217+
const server = createServer();
2218+
server.on('stream', (stream) => {
2219+
stream.respondWithFile('/some/file',
2220+
{ 'content-type': 'text/plain; charset=utf-8' },
2221+
{ waitForTrailers: true });
2222+
stream.on('wantTrailers', () => {
2223+
stream.sendTrailers({ ABC: 'some value to send' });
2224+
});
2225+
});
2226+
```
2227+
2228+
```cjs
19072229
const http2 = require('node:http2');
19082230
const server = http2.createServer();
19092231
server.on('stream', (stream) => {
@@ -2016,9 +2338,32 @@ added: v8.4.0
20162338
The `'stream'` event is emitted when a `'stream'` event has been emitted by
20172339
an `Http2Session` associated with the server.
20182340

2019-
See also [`Http2Session`'s `'stream'` event][].
2341+
See also [`Http2Session`'s `'stream'` event][].
2342+
2343+
```mjs
2344+
import { createServer, constants } from 'node:http2';
2345+
const {
2346+
HTTP2_HEADER_METHOD,
2347+
HTTP2_HEADER_PATH,
2348+
HTTP2_HEADER_STATUS,
2349+
HTTP2_HEADER_CONTENT_TYPE,
2350+
} = constants;
2351+
2352+
const server = createServer();
2353+
server.on('stream', (stream, headers, flags) => {
2354+
const method = headers[HTTP2_HEADER_METHOD];
2355+
const path = headers[HTTP2_HEADER_PATH];
2356+
// ...
2357+
stream.respond({
2358+
[HTTP2_HEADER_STATUS]: 200,
2359+
[HTTP2_HEADER_CONTENT_TYPE]: 'text/plain; charset=utf-8',
2360+
});
2361+
stream.write('hello ');
2362+
stream.end('world');
2363+
});
2364+
```
20202365

2021-
```js
2366+
```cjs
20222367
const http2 = require('node:http2');
20232368
const {
20242369
HTTP2_HEADER_METHOD,
@@ -2249,7 +2594,32 @@ an `Http2Session` associated with the server.
22492594

22502595
See also [`Http2Session`'s `'stream'` event][].
22512596

2252-
```js
2597+
```mjs
2598+
import { createSecureServer, constants } from 'node:http2';
2599+
const {
2600+
HTTP2_HEADER_METHOD,
2601+
HTTP2_HEADER_PATH,
2602+
HTTP2_HEADER_STATUS,
2603+
HTTP2_HEADER_CONTENT_TYPE,
2604+
} = constants;
2605+
2606+
const options = getOptionsSomehow();
2607+
2608+
const server = createSecureServer(options);
2609+
server.on('stream', (stream, headers, flags) => {
2610+
const method = headers[HTTP2_HEADER_METHOD];
2611+
const path = headers[HTTP2_HEADER_PATH];
2612+
// ...
2613+
stream.respond({
2614+
[HTTP2_HEADER_STATUS]: 200,
2615+
[HTTP2_HEADER_CONTENT_TYPE]: 'text/plain; charset=utf-8',
2616+
});
2617+
stream.write('hello ');
2618+
stream.end('world');
2619+
});
2620+
```
2621+
2622+
```cjs
22532623
const http2 = require('node:http2');
22542624
const {
22552625
HTTP2_HEADER_METHOD,
@@ -2533,7 +2903,27 @@ Since there are no browsers known that support
25332903
[`http2.createSecureServer()`][] is necessary when communicating
25342904
with browser clients.
25352905

2536-
```js
2906+
```mjs
2907+
import { createServer } from 'node:http2';
2908+
2909+
// Create an unencrypted HTTP/2 server.
2910+
// Since there are no browsers known that support
2911+
// unencrypted HTTP/2, the use of `createSecureServer()`
2912+
// is necessary when communicating with browser clients.
2913+
const server = createServer();
2914+
2915+
server.on('stream', (stream, headers) => {
2916+
stream.respond({
2917+
'content-type': 'text/html; charset=utf-8',
2918+
':status': 200,
2919+
});
2920+
stream.end('<h1>Hello World</h1>');
2921+
});
2922+
2923+
server.listen(8000);
2924+
```
2925+
2926+
```cjs
25372927
const http2 = require('node:http2');
25382928

25392929
// Create an unencrypted HTTP/2 server.
@@ -2675,7 +3065,30 @@ changes:
26753065
Returns a `tls.Server` instance that creates and manages `Http2Session`
26763066
instances.
26773067

2678-
```js
3068+
```mjs
3069+
import { createSecureServer } from 'node:http2';
3070+
import { readFileSync } from 'node:fs';
3071+
3072+
const options = {
3073+
key: readFileSync('server-key.pem'),
3074+
cert: readFileSync('server-cert.pem'),
3075+
};
3076+
3077+
// Create a secure HTTP/2 server
3078+
const server = createSecureServer(options);
3079+
3080+
server.on('stream', (stream, headers) => {
3081+
stream.respond({
3082+
'content-type': 'text/html; charset=utf-8',
3083+
':status': 200,
3084+
});
3085+
stream.end('<h1>Hello World</h1>');
3086+
});
3087+
3088+
server.listen(8443);
3089+
```
3090+
3091+
```cjs
26793092
const http2 = require('node:http2');
26803093
const fs = require('node:fs');
26813094

@@ -2807,7 +3220,16 @@ changes:
28073220

28083221
Returns a `ClientHttp2Session` instance.
28093222

2810-
```js
3223+
```mjs
3224+
import { connect } from 'node:http2';
3225+
const client = connect('https://localhost:1234');
3226+
3227+
/* Use the client */
3228+
3229+
client.close();
3230+
```
3231+
3232+
```cjs
28113233
const http2 = require('node:http2');
28123234
const client = http2.connect('https://localhost:1234');
28133235

@@ -2869,7 +3291,16 @@ Returns a `Buffer` instance containing serialized representation of the given
28693291
HTTP/2 settings as specified in the [HTTP/2][] specification. This is intended
28703292
for use with the `HTTP2-Settings` header field.
28713293

2872-
```js
3294+
```mjs
3295+
import { getPackedSettings } from 'node:http2';
3296+
3297+
const packed = getPackedSettings({ enablePush: false });
3298+
3299+
console.log(packed.toString('base64'));
3300+
// Prints: AAIAAAAA
3301+
```
3302+
3303+
```cjs
28733304
const http2 = require('node:http2');
28743305

28753306
const packed = http2.getPackedSettings({ enablePush: false });
@@ -2956,7 +3387,16 @@ For incoming headers:
29563387
* For duplicate `cookie` headers, the values are joined together with '; '.
29573388
* For all other headers, the values are joined together with ', '.
29583389

2959-
```js
3390+
```mjs
3391+
import { createServer } from 'node:http2';
3392+
const server = createServer();
3393+
server.on('stream', (stream, headers) => {
3394+
console.log(headers[':path']);
3395+
console.log(headers.ABC);
3396+
});
3397+
```
3398+
3399+
```cjs
29603400
const http2 = require('node:http2');
29613401
const server = http2.createServer();
29623402
server.on('stream', (stream, headers) => {
@@ -3104,7 +3544,22 @@ characters, per the requirements of the HTTP specification.
31043544
To receive pushed streams on the client, set a listener for the `'stream'`
31053545
event on the `ClientHttp2Session`:
31063546

3107-
```js
3547+
```mjs
3548+
import { connect } from 'node:http2';
3549+
3550+
const client = connect('http://localhost');
3551+
3552+
client.on('stream', (pushedStream, requestHeaders) => {
3553+
pushedStream.on('push', (responseHeaders) => {
3554+
// Process response headers
3555+
});
3556+
pushedStream.on('data', (chunk) => { /* handle pushed data */ });
3557+
});
3558+
3559+
const req = client.request({ ':path': '/' });
3560+
```
3561+
3562+
```cjs
31083563
const http2 = require('node:http2');
31093564

31103565
const client = http2.connect('http://localhost');
@@ -3126,7 +3581,20 @@ for TCP/IP connections.
31263581

31273582
A simple TCP Server:
31283583

3129-
```js
3584+
```mjs
3585+
import { createServer } from 'node:net';
3586+
3587+
const server = createServer((socket) => {
3588+
let name = '';
3589+
socket.setEncoding('utf8');
3590+
socket.on('data', (chunk) => name += chunk);
3591+
socket.on('end', () => socket.end(`hello ${name}`));
3592+
});
3593+
3594+
server.listen(8000);
3595+
```
3596+
3597+
```cjs
31303598
const net = require('node:net');
31313599

31323600
const server = net.createServer((socket) => {
@@ -3141,7 +3609,35 @@ server.listen(8000);
31413609

31423610
An HTTP/2 CONNECT proxy:
31433611

3144-
```js
3612+
```mjs
3613+
import { createServer, constants } from 'node:http2';
3614+
const { NGHTTP2_REFUSED_STREAM, NGHTTP2_CONNECT_ERROR } = constants;
3615+
import { connect } from 'node:net';
3616+
3617+
const proxy = createServer();
3618+
proxy.on('stream', (stream, headers) => {
3619+
if (headers[':method'] !== 'CONNECT') {
3620+
// Only accept CONNECT requests
3621+
stream.close(NGHTTP2_REFUSED_STREAM);
3622+
return;
3623+
}
3624+
const auth = new URL(`tcp://${headers[':authority']}`);
3625+
// It's a very good idea to verify that hostname and port are
3626+
// things this proxy should be connecting to.
3627+
const socket = connect(auth.port, auth.hostname, () => {
3628+
stream.respond();
3629+
socket.pipe(stream);
3630+
stream.pipe(socket);
3631+
});
3632+
socket.on('error', (error) => {
3633+
stream.close(NGHTTP2_CONNECT_ERROR);
3634+
});
3635+
});
3636+
3637+
proxy.listen(8001);
3638+
```
3639+
3640+
```cjs
31453641
const http2 = require('node:http2');
31463642
const { NGHTTP2_REFUSED_STREAM } = http2.constants;
31473643
const net = require('node:net');
@@ -3171,7 +3667,32 @@ proxy.listen(8001);
31713667

31723668
An HTTP/2 CONNECT client:
31733669

3174-
```js
3670+
```mjs
3671+
import { connect, constants } from 'node:http2';
3672+
3673+
const client = connect('http://localhost:8001');
3674+
3675+
// Must not specify the ':path' and ':scheme' headers
3676+
// for CONNECT requests or an error will be thrown.
3677+
const req = client.request({
3678+
':method': 'CONNECT',
3679+
':authority': 'localhost:8000',
3680+
});
3681+
3682+
req.on('response', (headers) => {
3683+
console.log(headers[constants.HTTP2_HEADER_STATUS]);
3684+
});
3685+
let data = '';
3686+
req.setEncoding('utf8');
3687+
req.on('data', (chunk) => data += chunk);
3688+
req.on('end', () => {
3689+
console.log(`The server says: ${data}`);
3690+
client.close();
3691+
});
3692+
req.end('Jane');
3693+
```
3694+
3695+
```cjs
31753696
const http2 = require('node:http2');
31763697

31773698
const client = http2.connect('http://localhost:8001');
@@ -3205,7 +3726,13 @@ method as a tunnel for other communication protocols (such as WebSockets).
32053726
The use of the Extended CONNECT Protocol is enabled by HTTP/2 servers by using
32063727
the `enableConnectProtocol` setting:
32073728

3208-
```js
3729+
```mjs
3730+
import { createServer } from 'node:http2';
3731+
const settings = { enableConnectProtocol: true };
3732+
const server = createServer({ settings });
3733+
```
3734+
3735+
```cjs
32093736
const http2 = require('node:http2');
32103737
const settings = { enableConnectProtocol: true };
32113738
const server = http2.createServer({ settings });
@@ -3215,7 +3742,18 @@ Once the client receives the `SETTINGS` frame from the server indicating that
32153742
the extended CONNECT may be used, it may send `CONNECT` requests that use the
32163743
`':protocol'` HTTP/2 pseudo-header:
32173744

3218-
```js
3745+
```mjs
3746+
import { connect } from 'node:http2';
3747+
const client = connect('http://localhost:8080');
3748+
client.on('remoteSettings', (settings) => {
3749+
if (settings.enableConnectProtocol) {
3750+
const req = client.request({ ':method': 'CONNECT', ':protocol': 'foo' });
3751+
// ...
3752+
}
3753+
});
3754+
```
3755+
3756+
```cjs
32193757
const http2 = require('node:http2');
32203758
const client = http2.connect('http://localhost:8080');
32213759
client.on('remoteSettings', (settings) => {
@@ -3238,7 +3776,17 @@ different implementation.
32383776
The following example creates an HTTP/2 server using the compatibility
32393777
API:
32403778

3241-
```js
3779+
```mjs
3780+
import { createServer } from 'node:http2';
3781+
const server = createServer((req, res) => {
3782+
res.setHeader('Content-Type', 'text/html');
3783+
res.setHeader('X-Foo', 'bar');
3784+
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
3785+
res.end('ok');
3786+
});
3787+
```
3788+
3789+
```cjs
32423790
const http2 = require('node:http2');
32433791
const server = http2.createServer((req, res) => {
32443792
res.setHeader('Content-Type', 'text/html');
@@ -3267,7 +3815,31 @@ features of HTTP/2.
32673815

32683816
The following example creates a server that supports both protocols:
32693817

3270-
```js
3818+
```mjs
3819+
import { createSecureServer } from 'node:http2';
3820+
import { readFileSync } from 'node:fs';
3821+
3822+
const cert = readFileSync('./cert.pem');
3823+
const key = readFileSync('./key.pem');
3824+
3825+
const server = createSecureServer(
3826+
{ cert, key, allowHTTP1: true },
3827+
onRequest,
3828+
).listen(8000);
3829+
3830+
function onRequest(req, res) {
3831+
// Detects if it is a HTTPS request or HTTP/2
3832+
const { socket: { alpnProtocol } } = req.httpVersion === '2.0' ?
3833+
req.stream.session : req;
3834+
res.writeHead(200, { 'content-type': 'application/json' });
3835+
res.end(JSON.stringify({
3836+
alpnProtocol,
3837+
httpVersion: req.httpVersion,
3838+
}));
3839+
}
3840+
```
3841+
3842+
```cjs
32713843
const { createSecureServer } = require('node:http2');
32723844
const { readFileSync } = require('node:fs');
32733845

@@ -3979,7 +4551,16 @@ more information.
39794551

39804552
All other interactions will be routed directly to the socket.
39814553

3982-
```js
4554+
```mjs
4555+
import { createServer } from 'node:http2';
4556+
const server = createServer((req, res) => {
4557+
const ip = req.socket.remoteAddress;
4558+
const port = req.socket.remotePort;
4559+
res.end(`Your IP address is ${ip} and your source port is ${port}.`);
4560+
}).listen(3000);
4561+
```
4562+
4563+
```cjs
39834564
const http2 = require('node:http2');
39844565
const server = http2.createServer((req, res) => {
39854566
const ip = req.socket.remoteAddress;
@@ -4190,7 +4771,22 @@ will result in a [`TypeError`][] being thrown.
41904771
The [Performance Observer][] API can be used to collect basic performance
41914772
metrics for each `Http2Session` and `Http2Stream` instance.
41924773

4193-
```js
4774+
```mjs
4775+
import { PerformanceObserver } from 'node:perf_hooks';
4776+
4777+
const obs = new PerformanceObserver((items) => {
4778+
const entry = items.getEntries()[0];
4779+
console.log(entry.entryType); // prints 'http2'
4780+
if (entry.name === 'Http2Session') {
4781+
// Entry contains statistics about the Http2Session
4782+
} else if (entry.name === 'Http2Stream') {
4783+
// Entry contains statistics about the Http2Stream
4784+
}
4785+
});
4786+
obs.observe({ entryTypes: ['http2'] });
4787+
```
4788+
4789+
```cjs
41944790
const { PerformanceObserver } = require('node:perf_hooks');
41954791

41964792
const obs = new PerformanceObserver((items) => {

0 commit comments

Comments
 (0)
Please sign in to comment.