1'use strict'; 2const common = require('../common'); 3const assert = require('node:assert'); 4const http = require('node:http'); 5const debug = require('node:util').debuglog('test'); 6 7const testResBody = 'response content\n'; 8 9{ 10 // Happy flow - string argument 11 12 const server = http.createServer(common.mustCall((req, res) => { 13 debug('Server sending early hints...'); 14 res.writeEarlyHints({ 15 link: '</styles.css>; rel=preload; as=style' 16 }); 17 18 debug('Server sending full response...'); 19 res.end(testResBody); 20 })); 21 22 server.listen(0, common.mustCall(() => { 23 const req = http.request({ 24 port: server.address().port, path: '/' 25 }); 26 27 debug('Client sending request...'); 28 29 req.on('information', common.mustCall((res) => { 30 assert.strictEqual(res.headers.link, '</styles.css>; rel=preload; as=style'); 31 })); 32 33 req.on('response', common.mustCall((res) => { 34 let body = ''; 35 36 assert.strictEqual(res.statusCode, 200, `Final status code was ${res.statusCode}, not 200.`); 37 38 res.on('data', (chunk) => { 39 body += chunk; 40 }); 41 42 res.on('end', common.mustCall(() => { 43 debug('Got full response.'); 44 assert.strictEqual(body, testResBody); 45 server.close(); 46 })); 47 })); 48 49 req.end(); 50 })); 51} 52 53{ 54 // Happy flow - array argument 55 56 const server = http.createServer(common.mustCall((req, res) => { 57 debug('Server sending early hints...'); 58 res.writeEarlyHints({ 59 link: [ 60 '</styles.css>; rel=preload; as=style', 61 '</scripts.js>; crossorigin; rel=preload; as=script', 62 '</scripts.js>; rel=preload; as=script; crossorigin', 63 ] 64 }); 65 66 debug('Server sending full response...'); 67 res.end(testResBody); 68 })); 69 70 server.listen(0, common.mustCall(() => { 71 const req = http.request({ 72 port: server.address().port, path: '/' 73 }); 74 debug('Client sending request...'); 75 76 req.on('information', common.mustCall((res) => { 77 assert.strictEqual( 78 res.headers.link, 79 '</styles.css>; rel=preload; as=style, </scripts.js>; crossorigin; ' + 80 'rel=preload; as=script, </scripts.js>; rel=preload; as=script; crossorigin' 81 ); 82 })); 83 84 req.on('response', common.mustCall((res) => { 85 let body = ''; 86 87 assert.strictEqual(res.statusCode, 200, `Final status code was ${res.statusCode}, not 200.`); 88 89 res.on('data', (chunk) => { 90 body += chunk; 91 }); 92 93 res.on('end', common.mustCall(() => { 94 debug('Got full response.'); 95 assert.strictEqual(body, testResBody); 96 server.close(); 97 })); 98 })); 99 100 req.end(); 101 })); 102} 103 104{ 105 // Happy flow - empty array 106 107 const server = http.createServer(common.mustCall((req, res) => { 108 debug('Server sending early hints...'); 109 res.writeEarlyHints({ 110 link: [] 111 }); 112 113 debug('Server sending full response...'); 114 res.end(testResBody); 115 })); 116 117 server.listen(0, common.mustCall(() => { 118 const req = http.request({ 119 port: server.address().port, path: '/' 120 }); 121 debug('Client sending request...'); 122 123 req.on('information', common.mustNotCall()); 124 125 req.on('response', common.mustCall((res) => { 126 let body = ''; 127 128 assert.strictEqual(res.statusCode, 200, `Final status code was ${res.statusCode}, not 200.`); 129 130 res.on('data', (chunk) => { 131 body += chunk; 132 }); 133 134 res.on('end', common.mustCall(() => { 135 debug('Got full response.'); 136 assert.strictEqual(body, testResBody); 137 server.close(); 138 })); 139 })); 140 141 req.end(); 142 })); 143} 144 145{ 146 // Happy flow - object argument with string 147 148 const server = http.createServer(common.mustCall((req, res) => { 149 debug('Server sending early hints...'); 150 res.writeEarlyHints({ 151 'link': '</styles.css>; rel=preload; as=style', 152 'x-trace-id': 'id for diagnostics' 153 }); 154 155 debug('Server sending full response...'); 156 res.end(testResBody); 157 })); 158 159 server.listen(0, common.mustCall(() => { 160 const req = http.request({ 161 port: server.address().port, path: '/' 162 }); 163 debug('Client sending request...'); 164 165 req.on('information', common.mustCall((res) => { 166 assert.strictEqual( 167 res.headers.link, 168 '</styles.css>; rel=preload; as=style' 169 ); 170 assert.strictEqual(res.headers['x-trace-id'], 'id for diagnostics'); 171 })); 172 173 req.on('response', common.mustCall((res) => { 174 let body = ''; 175 176 assert.strictEqual(res.statusCode, 200, `Final status code was ${res.statusCode}, not 200.`); 177 178 res.on('data', (chunk) => { 179 body += chunk; 180 }); 181 182 res.on('end', common.mustCall(() => { 183 debug('Got full response.'); 184 assert.strictEqual(body, testResBody); 185 server.close(); 186 })); 187 })); 188 189 req.end(); 190 })); 191} 192 193{ 194 // Happy flow - object argument with array of strings 195 196 const server = http.createServer(common.mustCall((req, res) => { 197 debug('Server sending early hints...'); 198 res.writeEarlyHints({ 199 'link': [ 200 '</styles.css>; rel=preload; as=style', 201 '</scripts.js>; rel=preload; as=script', 202 ], 203 'x-trace-id': 'id for diagnostics' 204 }); 205 206 debug('Server sending full response...'); 207 res.end(testResBody); 208 })); 209 210 server.listen(0, common.mustCall(() => { 211 const req = http.request({ 212 port: server.address().port, path: '/' 213 }); 214 debug('Client sending request...'); 215 216 req.on('information', common.mustCall((res) => { 217 assert.strictEqual( 218 res.headers.link, 219 '</styles.css>; rel=preload; as=style, </scripts.js>; rel=preload; as=script' 220 ); 221 assert.strictEqual(res.headers['x-trace-id'], 'id for diagnostics'); 222 })); 223 224 req.on('response', common.mustCall((res) => { 225 let body = ''; 226 227 assert.strictEqual(res.statusCode, 200, `Final status code was ${res.statusCode}, not 200.`); 228 229 res.on('data', (chunk) => { 230 body += chunk; 231 }); 232 233 res.on('end', common.mustCall(() => { 234 debug('Got full response.'); 235 assert.strictEqual(body, testResBody); 236 server.close(); 237 })); 238 })); 239 240 req.end(); 241 })); 242} 243 244{ 245 // Happy flow - empty object 246 247 const server = http.createServer(common.mustCall((req, res) => { 248 debug('Server sending early hints...'); 249 res.writeEarlyHints({}); 250 251 debug('Server sending full response...'); 252 res.end(testResBody); 253 })); 254 255 server.listen(0, common.mustCall(() => { 256 const req = http.request({ 257 port: server.address().port, path: '/' 258 }); 259 debug('Client sending request...'); 260 261 req.on('information', common.mustNotCall()); 262 263 req.on('response', common.mustCall((res) => { 264 let body = ''; 265 266 assert.strictEqual(res.statusCode, 200, `Final status code was ${res.statusCode}, not 200.`); 267 268 res.on('data', (chunk) => { 269 body += chunk; 270 }); 271 272 res.on('end', common.mustCall(() => { 273 debug('Got full response.'); 274 assert.strictEqual(body, testResBody); 275 server.close(); 276 })); 277 })); 278 279 req.end(); 280 })); 281} 282