mirror of
https://github.com/nodejs/node.git
synced 2025-05-11 12:55:53 +00:00
http: add options to http.createServer()
This adds the optional options argument to `http.createServer()`. It contains two options: the `IncomingMessage` and `ServerReponse` option. Backport-PR-URL: https://github.com/nodejs/node/pull/20456 PR-URL: https://github.com/nodejs/node/pull/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>
This commit is contained in:
parent
0cae3c3fe5
commit
01dc646382
@ -1663,10 +1663,21 @@ A collection of all the standard HTTP response status codes, and the
|
|||||||
short description of each. For example, `http.STATUS_CODES[404] === 'Not
|
short description of each. For example, `http.STATUS_CODES[404] === 'Not
|
||||||
Found'`.
|
Found'`.
|
||||||
|
|
||||||
## http.createServer([requestListener])
|
## http.createServer([options][, requestListener])
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.13
|
added: v0.1.13
|
||||||
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/15752
|
||||||
|
description: The `options` argument is supported now.
|
||||||
-->
|
-->
|
||||||
|
- `options` {Object}
|
||||||
|
* `IncomingMessage` {http.IncomingMessage} Specifies the IncomingMessage class
|
||||||
|
to be used. Useful for extending the original `IncomingMessage`. Defaults
|
||||||
|
to: `IncomingMessage`
|
||||||
|
* `ServerResponse` {http.ServerResponse} Specifies the ServerResponse class to
|
||||||
|
be used. Useful for extending the original `ServerResponse`. Defaults to:
|
||||||
|
`ServerResponse`
|
||||||
- `requestListener` {Function}
|
- `requestListener` {Function}
|
||||||
|
|
||||||
* Returns: {http.Server}
|
* Returns: {http.Server}
|
||||||
|
@ -65,7 +65,8 @@ See [`http.Server#keepAliveTimeout`][].
|
|||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.3.4
|
added: v0.3.4
|
||||||
-->
|
-->
|
||||||
- `options` {Object} Accepts `options` from [`tls.createServer()`][] and [`tls.createSecureContext()`][].
|
- `options` {Object} Accepts `options` from [`tls.createServer()`][],
|
||||||
|
[`tls.createSecureContext()`][] and [`http.createServer()`][].
|
||||||
- `requestListener` {Function} A listener to be added to the `request` event.
|
- `requestListener` {Function} A listener to be added to the `request` event.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -255,6 +256,7 @@ const req = https.request(options, (res) => {
|
|||||||
[`http.Server#setTimeout()`]: http.html#http_server_settimeout_msecs_callback
|
[`http.Server#setTimeout()`]: http.html#http_server_settimeout_msecs_callback
|
||||||
[`http.Server#timeout`]: http.html#http_server_timeout
|
[`http.Server#timeout`]: http.html#http_server_timeout
|
||||||
[`http.Server`]: http.html#http_class_http_server
|
[`http.Server`]: http.html#http_class_http_server
|
||||||
|
[`http.createServer()`]: http.html#httpcreateserveroptions-requestlistener
|
||||||
[`http.close()`]: http.html#http_server_close_callback
|
[`http.close()`]: http.html#http_server_close_callback
|
||||||
[`http.get()`]: http.html#http_http_get_options_callback
|
[`http.get()`]: http.html#http_http_get_options_callback
|
||||||
[`http.request()`]: http.html#http_http_request_options_callback
|
[`http.request()`]: http.html#http_http_request_options_callback
|
||||||
|
@ -34,6 +34,7 @@ const {
|
|||||||
|
|
||||||
const debug = require('util').debuglog('http');
|
const debug = require('util').debuglog('http');
|
||||||
|
|
||||||
|
const kIncomingMessage = Symbol('IncomingMessage');
|
||||||
const kOnHeaders = HTTPParser.kOnHeaders | 0;
|
const kOnHeaders = HTTPParser.kOnHeaders | 0;
|
||||||
const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
|
const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
|
||||||
const kOnBody = HTTPParser.kOnBody | 0;
|
const kOnBody = HTTPParser.kOnBody | 0;
|
||||||
@ -73,7 +74,11 @@ function parserOnHeadersComplete(versionMajor, versionMinor, headers, method,
|
|||||||
parser._url = '';
|
parser._url = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.incoming = new IncomingMessage(parser.socket);
|
// Parser is also used by http client
|
||||||
|
var ParserIncomingMessage = parser.socket && parser.socket.server ?
|
||||||
|
parser.socket.server[kIncomingMessage] : IncomingMessage;
|
||||||
|
|
||||||
|
parser.incoming = new ParserIncomingMessage(parser.socket);
|
||||||
parser.incoming.httpVersionMajor = versionMajor;
|
parser.incoming.httpVersionMajor = versionMajor;
|
||||||
parser.incoming.httpVersionMinor = versionMinor;
|
parser.incoming.httpVersionMinor = versionMinor;
|
||||||
parser.incoming.httpVersion = `${versionMajor}.${versionMinor}`;
|
parser.incoming.httpVersion = `${versionMajor}.${versionMinor}`;
|
||||||
@ -353,5 +358,6 @@ module.exports = {
|
|||||||
freeParser,
|
freeParser,
|
||||||
httpSocketSetup,
|
httpSocketSetup,
|
||||||
methods,
|
methods,
|
||||||
parsers
|
parsers,
|
||||||
|
kIncomingMessage
|
||||||
};
|
};
|
||||||
|
@ -33,6 +33,7 @@ const {
|
|||||||
continueExpression,
|
continueExpression,
|
||||||
chunkExpression,
|
chunkExpression,
|
||||||
httpSocketSetup,
|
httpSocketSetup,
|
||||||
|
kIncomingMessage,
|
||||||
_checkInvalidHeaderChar: checkInvalidHeaderChar
|
_checkInvalidHeaderChar: checkInvalidHeaderChar
|
||||||
} = require('_http_common');
|
} = require('_http_common');
|
||||||
const { OutgoingMessage } = require('_http_outgoing');
|
const { OutgoingMessage } = require('_http_outgoing');
|
||||||
@ -41,6 +42,9 @@ const {
|
|||||||
defaultTriggerAsyncIdScope,
|
defaultTriggerAsyncIdScope,
|
||||||
getOrSetAsyncId
|
getOrSetAsyncId
|
||||||
} = require('internal/async_hooks');
|
} = require('internal/async_hooks');
|
||||||
|
const { IncomingMessage } = require('_http_incoming');
|
||||||
|
|
||||||
|
const kServerResponse = Symbol('ServerResponse');
|
||||||
|
|
||||||
const STATUS_CODES = {
|
const STATUS_CODES = {
|
||||||
100: 'Continue',
|
100: 'Continue',
|
||||||
@ -260,9 +264,19 @@ function writeHead(statusCode, reason, obj) {
|
|||||||
// Docs-only deprecated: DEP0063
|
// Docs-only deprecated: DEP0063
|
||||||
ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead;
|
ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead;
|
||||||
|
|
||||||
|
function Server(options, requestListener) {
|
||||||
|
if (!(this instanceof Server)) return new Server(options, requestListener);
|
||||||
|
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
requestListener = options;
|
||||||
|
options = {};
|
||||||
|
} else if (options == null || typeof options === 'object') {
|
||||||
|
options = util._extend({}, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
this[kIncomingMessage] = options.IncomingMessage || IncomingMessage;
|
||||||
|
this[kServerResponse] = options.ServerResponse || ServerResponse;
|
||||||
|
|
||||||
function Server(requestListener) {
|
|
||||||
if (!(this instanceof Server)) return new Server(requestListener);
|
|
||||||
net.Server.call(this, { allowHalfOpen: true });
|
net.Server.call(this, { allowHalfOpen: true });
|
||||||
|
|
||||||
if (requestListener) {
|
if (requestListener) {
|
||||||
@ -578,7 +592,7 @@ function parserOnIncoming(server, socket, state, req, keepAlive) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = new ServerResponse(req);
|
var res = new server[kServerResponse](req);
|
||||||
res._onPendingData = updateOutgoingData.bind(undefined, socket, state);
|
res._onPendingData = updateOutgoingData.bind(undefined, socket, state);
|
||||||
|
|
||||||
res.shouldKeepAlive = keepAlive;
|
res.shouldKeepAlive = keepAlive;
|
||||||
@ -681,5 +695,6 @@ module.exports = {
|
|||||||
STATUS_CODES,
|
STATUS_CODES,
|
||||||
Server,
|
Server,
|
||||||
ServerResponse,
|
ServerResponse,
|
||||||
_connectionListener: connectionListener
|
_connectionListener: connectionListener,
|
||||||
|
kServerResponse
|
||||||
};
|
};
|
||||||
|
@ -30,6 +30,9 @@ const util = require('util');
|
|||||||
const { inherits } = util;
|
const { inherits } = util;
|
||||||
const debug = util.debuglog('https');
|
const debug = util.debuglog('https');
|
||||||
const { urlToOptions, searchParamsSymbol } = require('internal/url');
|
const { urlToOptions, searchParamsSymbol } = require('internal/url');
|
||||||
|
const { IncomingMessage, ServerResponse } = require('http');
|
||||||
|
const { kIncomingMessage } = require('_http_common');
|
||||||
|
const { kServerResponse } = require('_http_server');
|
||||||
|
|
||||||
function Server(opts, requestListener) {
|
function Server(opts, requestListener) {
|
||||||
if (!(this instanceof Server)) return new Server(opts, requestListener);
|
if (!(this instanceof Server)) return new Server(opts, requestListener);
|
||||||
@ -51,9 +54,10 @@ function Server(opts, requestListener) {
|
|||||||
opts.ALPNProtocols = ['http/1.1'];
|
opts.ALPNProtocols = ['http/1.1'];
|
||||||
}
|
}
|
||||||
|
|
||||||
tls.Server.call(this, opts, http._connectionListener);
|
this[kIncomingMessage] = opts.IncomingMessage || IncomingMessage;
|
||||||
|
this[kServerResponse] = opts.ServerResponse || ServerResponse;
|
||||||
|
|
||||||
this.httpAllowHalfOpen = false;
|
tls.Server.call(this, opts, http._connectionListener);
|
||||||
|
|
||||||
if (requestListener) {
|
if (requestListener) {
|
||||||
this.addListener('request', requestListener);
|
this.addListener('request', requestListener);
|
||||||
|
41
test/parallel/test-http-server-options-incoming-message.js
Normal file
41
test/parallel/test-http-server-options-incoming-message.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test covers http.Server({ IncomingMessage }) option:
|
||||||
|
* With IncomingMessage option the server should use
|
||||||
|
* the new class for creating req Object instead of the default
|
||||||
|
* http.IncomingMessage.
|
||||||
|
*/
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const http = require('http');
|
||||||
|
|
||||||
|
class MyIncomingMessage extends http.IncomingMessage {
|
||||||
|
getUserAgent() {
|
||||||
|
return this.headers['user-agent'] || 'unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = http.Server({
|
||||||
|
IncomingMessage: MyIncomingMessage
|
||||||
|
}, common.mustCall(function(req, res) {
|
||||||
|
assert.strictEqual(req.getUserAgent(), 'node-test');
|
||||||
|
res.statusCode = 200;
|
||||||
|
res.end();
|
||||||
|
}));
|
||||||
|
server.listen();
|
||||||
|
|
||||||
|
server.on('listening', function makeRequest() {
|
||||||
|
http.get({
|
||||||
|
port: this.address().port,
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'node-test'
|
||||||
|
}
|
||||||
|
}, (res) => {
|
||||||
|
assert.strictEqual(res.statusCode, 200);
|
||||||
|
res.on('end', () => {
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
res.resume();
|
||||||
|
});
|
||||||
|
});
|
35
test/parallel/test-http-server-options-server-response.js
Normal file
35
test/parallel/test-http-server-options-server-response.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test covers http.Server({ ServerResponse }) option:
|
||||||
|
* With ServerResponse option the server should use
|
||||||
|
* the new class for creating res Object instead of the default
|
||||||
|
* http.ServerResponse.
|
||||||
|
*/
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const http = require('http');
|
||||||
|
|
||||||
|
class MyServerResponse extends http.ServerResponse {
|
||||||
|
status(code) {
|
||||||
|
return this.writeHead(code, { 'Content-Type': 'text/plain' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = http.Server({
|
||||||
|
ServerResponse: MyServerResponse
|
||||||
|
}, common.mustCall(function(req, res) {
|
||||||
|
res.status(200);
|
||||||
|
res.end();
|
||||||
|
}));
|
||||||
|
server.listen();
|
||||||
|
|
||||||
|
server.on('listening', function makeRequest() {
|
||||||
|
http.get({ port: this.address().port }, (res) => {
|
||||||
|
assert.strictEqual(res.statusCode, 200);
|
||||||
|
res.on('end', () => {
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
res.resume();
|
||||||
|
});
|
||||||
|
});
|
51
test/parallel/test-https-server-options-incoming-message.js
Normal file
51
test/parallel/test-https-server-options-incoming-message.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test covers http.Server({ IncomingMessage }) option:
|
||||||
|
* With IncomingMessage option the server should use
|
||||||
|
* the new class for creating req Object instead of the default
|
||||||
|
* http.IncomingMessage.
|
||||||
|
*/
|
||||||
|
const common = require('../common');
|
||||||
|
const fixtures = require('../common/fixtures');
|
||||||
|
|
||||||
|
if (!common.hasCrypto)
|
||||||
|
common.skip('missing crypto');
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const http = require('http');
|
||||||
|
const https = require('https');
|
||||||
|
|
||||||
|
class MyIncomingMessage extends http.IncomingMessage {
|
||||||
|
getUserAgent() {
|
||||||
|
return this.headers['user-agent'] || 'unknown';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = https.createServer({
|
||||||
|
key: fixtures.readKey('agent1-key.pem'),
|
||||||
|
cert: fixtures.readKey('agent1-cert.pem'),
|
||||||
|
ca: fixtures.readKey('ca1-cert.pem'),
|
||||||
|
IncomingMessage: MyIncomingMessage
|
||||||
|
}, common.mustCall(function(req, res) {
|
||||||
|
assert.strictEqual(req.getUserAgent(), 'node-test');
|
||||||
|
res.statusCode = 200;
|
||||||
|
res.end();
|
||||||
|
}));
|
||||||
|
server.listen();
|
||||||
|
|
||||||
|
server.on('listening', function makeRequest() {
|
||||||
|
https.get({
|
||||||
|
port: this.address().port,
|
||||||
|
rejectUnauthorized: false,
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'node-test'
|
||||||
|
}
|
||||||
|
}, (res) => {
|
||||||
|
assert.strictEqual(res.statusCode, 200);
|
||||||
|
res.on('end', () => {
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
res.resume();
|
||||||
|
});
|
||||||
|
});
|
47
test/parallel/test-https-server-options-server-response.js
Normal file
47
test/parallel/test-https-server-options-server-response.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test covers http.Server({ ServerResponse }) option:
|
||||||
|
* With ServerResponse option the server should use
|
||||||
|
* the new class for creating res Object instead of the default
|
||||||
|
* http.ServerResponse.
|
||||||
|
*/
|
||||||
|
const common = require('../common');
|
||||||
|
const fixtures = require('../common/fixtures');
|
||||||
|
|
||||||
|
if (!common.hasCrypto)
|
||||||
|
common.skip('missing crypto');
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const http = require('http');
|
||||||
|
const https = require('https');
|
||||||
|
|
||||||
|
class MyServerResponse extends http.ServerResponse {
|
||||||
|
status(code) {
|
||||||
|
return this.writeHead(code, { 'Content-Type': 'text/plain' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = https.createServer({
|
||||||
|
key: fixtures.readKey('agent1-key.pem'),
|
||||||
|
cert: fixtures.readKey('agent1-cert.pem'),
|
||||||
|
ca: fixtures.readKey('ca1-cert.pem'),
|
||||||
|
ServerResponse: MyServerResponse
|
||||||
|
}, common.mustCall(function(req, res) {
|
||||||
|
res.status(200);
|
||||||
|
res.end();
|
||||||
|
}));
|
||||||
|
server.listen();
|
||||||
|
|
||||||
|
server.on('listening', function makeRequest() {
|
||||||
|
https.get({
|
||||||
|
port: this.address().port,
|
||||||
|
rejectUnauthorized: false
|
||||||
|
}, (res) => {
|
||||||
|
assert.strictEqual(res.statusCode, 200);
|
||||||
|
res.on('end', () => {
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
res.resume();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user