1'use strict';
2
3const common = require('../common');
4if (!common.hasCrypto) common.skip('missing crypto');
5
6const assert = require('node:assert');
7const http2 = require('node:http2');
8const debug = require('node:util').debuglog('test');
9
10const testResBody = 'response content';
11
12{
13  // Happy flow - string argument
14
15  const server = http2.createServer();
16
17  server.on('request', common.mustCall((req, res) => {
18    debug('Server sending early hints...');
19    res.writeEarlyHints({
20      link: '</styles.css>; rel=preload; as=style'
21    });
22
23    debug('Server sending full response...');
24    res.end(testResBody);
25  }));
26
27  server.listen(0);
28
29  server.on('listening', common.mustCall(() => {
30    const client = http2.connect(`http://localhost:${server.address().port}`);
31    const req = client.request();
32
33    debug('Client sending request...');
34
35    req.on('headers', common.mustCall((headers) => {
36      assert.notStrictEqual(headers, undefined);
37      assert.strictEqual(headers[':status'], 103);
38      assert.strictEqual(headers.link, '</styles.css>; rel=preload; as=style');
39    }));
40
41    req.on('response', common.mustCall((headers) => {
42      assert.strictEqual(headers[':status'], 200);
43    }));
44
45    let data = '';
46    req.on('data', common.mustCallAtLeast((d) => data += d));
47
48    req.on('end', common.mustCall(() => {
49      debug('Got full response.');
50      assert.strictEqual(data, testResBody);
51      client.close();
52      server.close();
53    }));
54  }));
55}
56
57{
58  // Happy flow - array argument
59
60  const server = http2.createServer();
61
62  server.on('request', common.mustCall((req, res) => {
63    debug('Server sending early hints...');
64    res.writeEarlyHints({
65      link: [
66        '</styles.css>; rel=preload; as=style',
67        '</scripts.js>; rel=preload; as=script',
68      ]
69    });
70
71    debug('Server sending full response...');
72    res.end(testResBody);
73  }));
74
75  server.listen(0);
76
77  server.on('listening', common.mustCall(() => {
78    const client = http2.connect(`http://localhost:${server.address().port}`);
79    const req = client.request();
80
81    debug('Client sending request...');
82
83    req.on('headers', common.mustCall((headers) => {
84      assert.notStrictEqual(headers, undefined);
85      assert.strictEqual(headers[':status'], 103);
86      assert.strictEqual(
87        headers.link,
88        '</styles.css>; rel=preload; as=style, </scripts.js>; rel=preload; as=script'
89      );
90    }));
91
92    req.on('response', common.mustCall((headers) => {
93      assert.strictEqual(headers[':status'], 200);
94    }));
95
96    let data = '';
97    req.on('data', common.mustCallAtLeast((d) => data += d));
98
99    req.on('end', common.mustCall(() => {
100      debug('Got full response.');
101      assert.strictEqual(data, testResBody);
102      client.close();
103      server.close();
104    }));
105  }));
106}
107
108{
109  // Happy flow - empty array
110
111  const server = http2.createServer();
112
113  server.on('request', common.mustCall((req, res) => {
114    debug('Server sending early hints...');
115    res.writeEarlyHints({
116      link: []
117    });
118
119    debug('Server sending full response...');
120    res.end(testResBody);
121  }));
122
123  server.listen(0);
124
125  server.on('listening', common.mustCall(() => {
126    const client = http2.connect(`http://localhost:${server.address().port}`);
127    const req = client.request();
128
129    debug('Client sending request...');
130
131    req.on('headers', common.mustNotCall());
132
133    req.on('response', common.mustCall((headers) => {
134      assert.strictEqual(headers[':status'], 200);
135    }));
136
137    let data = '';
138    req.on('data', common.mustCallAtLeast((d) => data += d));
139
140    req.on('end', common.mustCall(() => {
141      debug('Got full response.');
142      assert.strictEqual(data, testResBody);
143      client.close();
144      server.close();
145    }));
146  }));
147}
148