Skip to content

Commit 9c87898

Browse files
author
Wing Leung
committed
src: add writeEarlyHints function to ServerResponse
1 parent f136e7e commit 9c87898

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

doc/api/http.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,6 +2131,11 @@ Sends a HTTP/1.1 100 Continue message to the client, indicating that
21312131
the request body should be sent. See the [`'checkContinue'`][] event on
21322132
`Server`.
21332133

2134+
### `response.writeEarlyHints()`
2135+
2136+
Sends a HTTP/1.1 103 Early Hints message to the client with a Link header, indicating that
2137+
the user agent can preload/preconnect the linked resources.
2138+
21342139
### `response.writeHead(statusCode[, statusMessage][, headers])`
21352140

21362141
<!-- YAML

lib/_http_server.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,20 @@ ServerResponse.prototype.writeProcessing = function writeProcessing(cb) {
295295
this._writeRaw('HTTP/1.1 102 Processing\r\n\r\n', 'ascii', cb);
296296
};
297297

298+
ServerResponse.prototype.writeEarlyHints = function writeEarlyHints(links, cb) {
299+
let head = 'HTTP/1.1 103 Early Hints\r\n'
300+
301+
if (typeof links === 'string') {
302+
head += 'Link: ' + links + '\r\n';
303+
} else if (Array.isArray(links)) {
304+
head += 'Link: ' + links.join(',') + '\r\n';
305+
}
306+
307+
head += '\r\n';
308+
309+
this._writeRaw(head, 'ascii', cb);
310+
};
311+
298312
ServerResponse.prototype._implicitHeader = function _implicitHeader() {
299313
this.writeHead(this.statusCode);
300314
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const http = require('http');
5+
const debug = require('util').debuglog('test');
6+
7+
const testResBody = 'response content\n';
8+
9+
const server = http.createServer((req, res) => {
10+
debug(`Server sending early hints...`);
11+
12+
res.writeEarlyHints([
13+
'</styles.css>; rel=preload; as=style',
14+
'</scripts.js>; rel=preload; as=script'
15+
]);
16+
17+
debug('Server sending full response...');
18+
res.writeHead(200, {
19+
'Content-Type': 'text/plain',
20+
'ABCD': '1'
21+
});
22+
23+
res.end(testResBody);
24+
});
25+
26+
server.listen(0, function() {
27+
const req = http.request({
28+
port: this.address().port,
29+
path: '/'
30+
});
31+
32+
req.end();
33+
debug('Client sending request...');
34+
35+
req.on('information', (res) => {
36+
assert.strictEqual(res.headers.link, '</styles.css>; rel=preload; as=style,</scripts.js>; rel=preload; as=script');
37+
});
38+
39+
req.on('response', function(res) {
40+
let body = '';
41+
42+
assert.strictEqual(
43+
res.statusCode, 200,
44+
`Final status code was ${res.statusCode}, not 200.`
45+
);
46+
res.setEncoding('utf8');
47+
res.on('data', function(chunk) { body += chunk; });
48+
res.on('end', function() {
49+
debug('Got full response.');
50+
assert.strictEqual(body, testResBody);
51+
server.close();
52+
});
53+
});
54+
});
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const http = require('http');
5+
const debug = require('util').debuglog('test');
6+
7+
const testResBody = 'response content\n';
8+
9+
const server = http.createServer((req, res) => {
10+
debug(`Server sending early hints...`);
11+
12+
res.writeEarlyHints('</styles.css>; rel=preload; as=style');
13+
14+
debug('Server sending full response...');
15+
res.writeHead(200, {
16+
'Content-Type': 'text/plain',
17+
'ABCD': '1'
18+
});
19+
20+
res.end(testResBody);
21+
});
22+
23+
server.listen(0, function() {
24+
const req = http.request({
25+
port: this.address().port,
26+
path: '/'
27+
});
28+
29+
req.end();
30+
debug('Client sending request...');
31+
32+
req.on('information', (res) => {
33+
assert.strictEqual(res.headers.link, '</styles.css>; rel=preload; as=style');
34+
});
35+
36+
req.on('response', function(res) {
37+
let body = '';
38+
39+
assert.strictEqual(
40+
res.statusCode, 200,
41+
`Final status code was ${res.statusCode}, not 200.`
42+
);
43+
res.setEncoding('utf8');
44+
res.on('data', function(chunk) { body += chunk; });
45+
res.on('end', function() {
46+
debug('Got full response.');
47+
assert.strictEqual(body, testResBody);
48+
server.close();
49+
});
50+
});
51+
});

0 commit comments

Comments
 (0)