Skip to content

Commit c247cb0

Browse 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 <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Evan Lucas <[email protected]>
1 parent 7a432c1 commit c247cb0

9 files changed

+222
-9
lines changed

‎doc/api/http.md‎

Lines changed: 12 additions & 2 deletions
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}

‎doc/api/https.md‎

Lines changed: 3 additions & 1 deletion
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

‎lib/_http_common.js‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const{
3434

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

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

76-
parser.incoming=newIncomingMessage(parser.socket);
77+
// Parser is also used by http client
78+
varParserIncomingMessage=parser.socket&&parser.socket.server ?
79+
parser.socket.server[kIncomingMessage] : IncomingMessage;
80+
81+
parser.incoming=newParserIncomingMessage(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
};

‎lib/_http_server.js‎

Lines 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
consterrors=require('internal/errors');
4547
constBuffer=require('buffer').Buffer;
4648

49+
constkServerResponse=Symbol('ServerResponse');
50+
4751
constSTATUS_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+
functionServer(options,requestListener){
271+
if(!(thisinstanceofServer))returnnewServer(options,requestListener);
272+
273+
if(typeofoptions==='function'){
274+
requestListener=options;
275+
options={};
276+
}elseif(options==null||typeofoptions==='object'){
277+
options=util._extend({},options);
278+
}
279+
280+
this[kIncomingMessage]=options.IncomingMessage||IncomingMessage;
281+
this[kServerResponse]=options.ServerResponse||ServerResponse;
266282

267-
functionServer(requestListener){
268-
if(!(thisinstanceofServer))returnnewServer(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-
varres=newServerResponse(req);
604+
varres=newserver[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
};

‎lib/https.js‎

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

4043
functionServer(opts,requestListener){
4144
if(!(thisinstanceofServer))returnnewServer(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;
Lines 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+
constcommon=require('../common');
10+
constassert=require('assert');
11+
consthttp=require('http');
12+
13+
classMyIncomingMessageextendshttp.IncomingMessage{
14+
getUserAgent(){
15+
returnthis.headers['user-agent']||'unknown';
16+
}
17+
}
18+
19+
constserver=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',functionmakeRequest(){
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+
});
Lines 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+
constcommon=require('../common');
10+
constassert=require('assert');
11+
consthttp=require('http');
12+
13+
classMyServerResponseextendshttp.ServerResponse{
14+
status(code){
15+
returnthis.writeHead(code,{'Content-Type': 'text/plain'});
16+
}
17+
}
18+
19+
constserver=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',functionmakeRequest(){
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+
});
Lines 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+
constcommon=require('../common');
10+
constfixtures=require('../common/fixtures');
11+
12+
if(!common.hasCrypto)
13+
common.skip('missing crypto');
14+
15+
constassert=require('assert');
16+
consthttp=require('http');
17+
consthttps=require('https');
18+
19+
classMyIncomingMessageextendshttp.IncomingMessage{
20+
getUserAgent(){
21+
returnthis.headers['user-agent']||'unknown';
22+
}
23+
}
24+
25+
constserver=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',functionmakeRequest(){
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+
});
Lines 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+
constcommon=require('../common');
10+
constfixtures=require('../common/fixtures');
11+
12+
if(!common.hasCrypto)
13+
common.skip('missing crypto');
14+
15+
constassert=require('assert');
16+
consthttp=require('http');
17+
consthttps=require('https');
18+
19+
classMyServerResponseextendshttp.ServerResponse{
20+
status(code){
21+
returnthis.writeHead(code,{'Content-Type': 'text/plain'});
22+
}
23+
}
24+
25+
constserver=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',functionmakeRequest(){
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)