Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c247cb0

Browse filesBrowse files
Peter MartonMylesBorins
authored andcommitted
http: add options to http.createServer()
This adds the optional options argument to `http.createServer()`. It contains two options: the `IncomingMessage` and `ServerReponse` option. PR-URL: #15752 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Evan Lucas <evanlucas@me.com>
1 parent 7a432c1 commit c247cb0
Copy full SHA for c247cb0
Expand file treeCollapse file tree

9 files changed

+222
-9
lines changed
Open diff view settings
Collapse file

‎doc/api/http.md‎

Copy file name to clipboardExpand all lines: doc/api/http.md
+12-2Lines changed: 12 additions & 2 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -1663,10 +1663,20 @@ A collection of all the standard HTTP response status codes, and the
16631663
short description of each. For example, `http.STATUS_CODES[404] === 'Not
16641664
Found'`.
16651665

1666-
## http.createServer([requestListener])
1666+
## http.createServer([options][, requestListener])
16671667
<!-- YAML
16681668
added: v0.1.13
1669-
-->
1669+
- version: REPLACEME
1670+
pr-url: https://github.com/nodejs/node/pull/15752
1671+
description: The `options` argument is supported now.
1672+
-->
1673+
- `options` {Object}
1674+
* `IncomingMessage` {http.IncomingMessage} Specifies the IncomingMessage class
1675+
to be used. Useful for extending the original `IncomingMessage`. Defaults
1676+
to: `IncomingMessage`
1677+
* `ServerResponse` {http.ServerResponse} Specifies the ServerResponse class to
1678+
be used. Useful for extending the original `ServerResponse`. Defaults to:
1679+
`ServerResponse`
16701680
- `requestListener` {Function}
16711681

16721682
* Returns: {http.Server}
Collapse file

‎doc/api/https.md‎

Copy file name to clipboardExpand all lines: doc/api/https.md
+3-1Lines changed: 3 additions & 1 deletion
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ See [`http.Server#keepAliveTimeout`][].
6565
<!-- YAML
6666
added: v0.3.4
6767
-->
68-
- `options` {Object} Accepts `options` from [`tls.createServer()`][] and [`tls.createSecureContext()`][].
68+
- `options` {Object} Accepts `options` from [`tls.createServer()`][],
69+
[`tls.createSecureContext()`][] and [`http.createServer()`][].
6970
- `requestListener` {Function} A listener to be added to the `request` event.
7071

7172
Example:
@@ -258,6 +259,7 @@ const req = https.request(options, (res) => {
258259
[`http.Server#setTimeout()`]: http.html#http_server_settimeout_msecs_callback
259260
[`http.Server#timeout`]: http.html#http_server_timeout
260261
[`http.Server`]: http.html#http_class_http_server
262+
[`http.createServer()`]: http.html#httpcreateserveroptions-requestlistener
261263
[`http.close()`]: http.html#http_server_close_callback
262264
[`http.get()`]: http.html#http_http_get_options_callback
263265
[`http.request()`]: http.html#http_http_request_options_callback
Collapse file

‎lib/_http_common.js‎

Copy file name to clipboardExpand all lines: lib/_http_common.js
+8-2Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const {
3434

3535
const debug = require('util').debuglog('http');
3636

37+
const kIncomingMessage = Symbol('IncomingMessage');
3738
const kOnHeaders = HTTPParser.kOnHeaders | 0;
3839
const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
3940
const kOnBody = HTTPParser.kOnBody | 0;
@@ -73,7 +74,11 @@ function parserOnHeadersComplete(versionMajor, versionMinor, headers, method,
7374
parser._url = '';
7475
}
7576

76-
parser.incoming = new IncomingMessage(parser.socket);
77+
// Parser is also used by http client
78+
var ParserIncomingMessage = parser.socket && parser.socket.server ?
79+
parser.socket.server[kIncomingMessage] : IncomingMessage;
80+
81+
parser.incoming = new ParserIncomingMessage(parser.socket);
7782
parser.incoming.httpVersionMajor = versionMajor;
7883
parser.incoming.httpVersionMinor = versionMinor;
7984
parser.incoming.httpVersion = `${versionMajor}.${versionMinor}`;
@@ -300,5 +305,6 @@ module.exports = {
300305
freeParser,
301306
httpSocketSetup,
302307
methods,
303-
parsers
308+
parsers,
309+
kIncomingMessage
304310
};
Collapse file

‎lib/_http_server.js‎

Copy file name to clipboardExpand all lines: lib/_http_server.js
+19-4Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const {
3333
continueExpression,
3434
chunkExpression,
3535
httpSocketSetup,
36+
kIncomingMessage,
3637
_checkInvalidHeaderChar: checkInvalidHeaderChar
3738
} = require('_http_common');
3839
const { OutgoingMessage } = require('_http_outgoing');
@@ -41,9 +42,12 @@ const {
4142
defaultTriggerAsyncIdScope,
4243
getOrSetAsyncId
4344
} = require('internal/async_hooks');
45+
const { IncomingMessage } = require('_http_incoming');
4446
const errors = require('internal/errors');
4547
const Buffer = require('buffer').Buffer;
4648

49+
const kServerResponse = Symbol('ServerResponse');
50+
4751
const STATUS_CODES = {
4852
100: 'Continue',
4953
101: 'Switching Protocols',
@@ -263,9 +267,19 @@ function writeHead(statusCode, reason, obj) {
263267
// Docs-only deprecated: DEP0063
264268
ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead;
265269

270+
function Server(options, requestListener) {
271+
if (!(this instanceof Server)) return new Server(options, requestListener);
272+
273+
if (typeof options === 'function') {
274+
requestListener = options;
275+
options = {};
276+
} else if (options == null || typeof options === 'object') {
277+
options = util._extend({}, options);
278+
}
279+
280+
this[kIncomingMessage] = options.IncomingMessage || IncomingMessage;
281+
this[kServerResponse] = options.ServerResponse || ServerResponse;
266282

267-
function Server(requestListener) {
268-
if (!(this instanceof Server)) return new Server(requestListener);
269283
net.Server.call(this, { allowHalfOpen: true });
270284

271285
if (requestListener) {
@@ -587,7 +601,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
587601
}
588602
}
589603

590-
var res = new ServerResponse(req);
604+
var res = new server[kServerResponse](req);
591605
res._onPendingData = updateOutgoingData.bind(undefined, socket, state);
592606

593607
res.shouldKeepAlive = keepAlive;
@@ -690,5 +704,6 @@ module.exports = {
690704
STATUS_CODES,
691705
Server,
692706
ServerResponse,
693-
_connectionListener: connectionListener
707+
_connectionListener: connectionListener,
708+
kServerResponse
694709
};
Collapse file

‎lib/https.js‎

Copy file name to clipboardExpand all lines: lib/https.js
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ const { inherits } = util;
3636
const debug = util.debuglog('https');
3737
const { urlToOptions, searchParamsSymbol } = require('internal/url');
3838
const errors = require('internal/errors');
39+
const { IncomingMessage, ServerResponse } = require('http');
40+
const { kIncomingMessage } = require('_http_common');
41+
const { kServerResponse } = require('_http_server');
3942

4043
function Server(opts, requestListener) {
4144
if (!(this instanceof Server)) return new Server(opts, requestListener);
@@ -57,6 +60,9 @@ function Server(opts, requestListener) {
5760
opts.ALPNProtocols = ['http/1.1'];
5861
}
5962

63+
this[kIncomingMessage] = opts.IncomingMessage || IncomingMessage;
64+
this[kServerResponse] = opts.ServerResponse || ServerResponse;
65+
6066
tls.Server.call(this, opts, _connectionListener);
6167

6268
this.httpAllowHalfOpen = false;
Collapse file
+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict';
2+
3+
/**
4+
* This test covers http.Server({ IncomingMessage }) option:
5+
* With IncomingMessage option the server should use
6+
* the new class for creating req Object instead of the default
7+
* http.IncomingMessage.
8+
*/
9+
const common = require('../common');
10+
const assert = require('assert');
11+
const http = require('http');
12+
13+
class MyIncomingMessage extends http.IncomingMessage {
14+
getUserAgent() {
15+
return this.headers['user-agent'] || 'unknown';
16+
}
17+
}
18+
19+
const server = http.Server({
20+
IncomingMessage: MyIncomingMessage
21+
}, common.mustCall(function(req, res) {
22+
assert.strictEqual(req.getUserAgent(), 'node-test');
23+
res.statusCode = 200;
24+
res.end();
25+
}));
26+
server.listen();
27+
28+
server.on('listening', function makeRequest() {
29+
http.get({
30+
port: this.address().port,
31+
headers: {
32+
'User-Agent': 'node-test'
33+
}
34+
}, (res) => {
35+
assert.strictEqual(res.statusCode, 200);
36+
res.on('end', () => {
37+
server.close();
38+
});
39+
res.resume();
40+
});
41+
});
Collapse file
+35Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
3+
/**
4+
* This test covers http.Server({ ServerResponse }) option:
5+
* With ServerResponse option the server should use
6+
* the new class for creating res Object instead of the default
7+
* http.ServerResponse.
8+
*/
9+
const common = require('../common');
10+
const assert = require('assert');
11+
const http = require('http');
12+
13+
class MyServerResponse extends http.ServerResponse {
14+
status(code) {
15+
return this.writeHead(code, { 'Content-Type': 'text/plain' });
16+
}
17+
}
18+
19+
const server = http.Server({
20+
ServerResponse: MyServerResponse
21+
}, common.mustCall(function(req, res) {
22+
res.status(200);
23+
res.end();
24+
}));
25+
server.listen();
26+
27+
server.on('listening', function makeRequest() {
28+
http.get({ port: this.address().port }, (res) => {
29+
assert.strictEqual(res.statusCode, 200);
30+
res.on('end', () => {
31+
server.close();
32+
});
33+
res.resume();
34+
});
35+
});
Collapse file
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
'use strict';
2+
3+
/**
4+
* This test covers http.Server({ IncomingMessage }) option:
5+
* With IncomingMessage option the server should use
6+
* the new class for creating req Object instead of the default
7+
* http.IncomingMessage.
8+
*/
9+
const common = require('../common');
10+
const fixtures = require('../common/fixtures');
11+
12+
if (!common.hasCrypto)
13+
common.skip('missing crypto');
14+
15+
const assert = require('assert');
16+
const http = require('http');
17+
const https = require('https');
18+
19+
class MyIncomingMessage extends http.IncomingMessage {
20+
getUserAgent() {
21+
return this.headers['user-agent'] || 'unknown';
22+
}
23+
}
24+
25+
const server = https.createServer({
26+
key: fixtures.readKey('agent1-key.pem'),
27+
cert: fixtures.readKey('agent1-cert.pem'),
28+
ca: fixtures.readKey('ca1-cert.pem'),
29+
IncomingMessage: MyIncomingMessage
30+
}, common.mustCall(function(req, res) {
31+
assert.strictEqual(req.getUserAgent(), 'node-test');
32+
res.statusCode = 200;
33+
res.end();
34+
}));
35+
server.listen();
36+
37+
server.on('listening', function makeRequest() {
38+
https.get({
39+
port: this.address().port,
40+
rejectUnauthorized: false,
41+
headers: {
42+
'User-Agent': 'node-test'
43+
}
44+
}, (res) => {
45+
assert.strictEqual(res.statusCode, 200);
46+
res.on('end', () => {
47+
server.close();
48+
});
49+
res.resume();
50+
});
51+
});
Collapse file
+47Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict';
2+
3+
/**
4+
* This test covers http.Server({ ServerResponse }) option:
5+
* With ServerResponse option the server should use
6+
* the new class for creating res Object instead of the default
7+
* http.ServerResponse.
8+
*/
9+
const common = require('../common');
10+
const fixtures = require('../common/fixtures');
11+
12+
if (!common.hasCrypto)
13+
common.skip('missing crypto');
14+
15+
const assert = require('assert');
16+
const http = require('http');
17+
const https = require('https');
18+
19+
class MyServerResponse extends http.ServerResponse {
20+
status(code) {
21+
return this.writeHead(code, { 'Content-Type': 'text/plain' });
22+
}
23+
}
24+
25+
const server = https.createServer({
26+
key: fixtures.readKey('agent1-key.pem'),
27+
cert: fixtures.readKey('agent1-cert.pem'),
28+
ca: fixtures.readKey('ca1-cert.pem'),
29+
ServerResponse: MyServerResponse
30+
}, common.mustCall(function(req, res) {
31+
res.status(200);
32+
res.end();
33+
}));
34+
server.listen();
35+
36+
server.on('listening', function makeRequest() {
37+
https.get({
38+
port: this.address().port,
39+
rejectUnauthorized: false
40+
}, (res) => {
41+
assert.strictEqual(res.statusCode, 200);
42+
res.on('end', () => {
43+
server.close();
44+
});
45+
res.resume();
46+
});
47+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.