mirror of
https://github.com/nodejs/node.git
synced 2025-05-08 02:52:29 +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
|
||||
Found'`.
|
||||
|
||||
## http.createServer([requestListener])
|
||||
## http.createServer([options][, requestListener])
|
||||
<!-- YAML
|
||||
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}
|
||||
|
||||
* Returns: {http.Server}
|
||||
|
@ -65,7 +65,8 @@ See [`http.Server#keepAliveTimeout`][].
|
||||
<!-- YAML
|
||||
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.
|
||||
|
||||
Example:
|
||||
@ -255,6 +256,7 @@ const req = https.request(options, (res) => {
|
||||
[`http.Server#setTimeout()`]: http.html#http_server_settimeout_msecs_callback
|
||||
[`http.Server#timeout`]: http.html#http_server_timeout
|
||||
[`http.Server`]: http.html#http_class_http_server
|
||||
[`http.createServer()`]: http.html#httpcreateserveroptions-requestlistener
|
||||
[`http.close()`]: http.html#http_server_close_callback
|
||||
[`http.get()`]: http.html#http_http_get_options_callback
|
||||
[`http.request()`]: http.html#http_http_request_options_callback
|
||||
|
@ -34,6 +34,7 @@ const {
|
||||
|
||||
const debug = require('util').debuglog('http');
|
||||
|
||||
const kIncomingMessage = Symbol('IncomingMessage');
|
||||
const kOnHeaders = HTTPParser.kOnHeaders | 0;
|
||||
const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
|
||||
const kOnBody = HTTPParser.kOnBody | 0;
|
||||
@ -73,7 +74,11 @@ function parserOnHeadersComplete(versionMajor, versionMinor, headers, method,
|
||||
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.httpVersionMinor = versionMinor;
|
||||
parser.incoming.httpVersion = `${versionMajor}.${versionMinor}`;
|
||||
@ -353,5 +358,6 @@ module.exports = {
|
||||
freeParser,
|
||||
httpSocketSetup,
|
||||
methods,
|
||||
parsers
|
||||
parsers,
|
||||
kIncomingMessage
|
||||
};
|
||||
|
@ -33,6 +33,7 @@ const {
|
||||
continueExpression,
|
||||
chunkExpression,
|
||||
httpSocketSetup,
|
||||
kIncomingMessage,
|
||||
_checkInvalidHeaderChar: checkInvalidHeaderChar
|
||||
} = require('_http_common');
|
||||
const { OutgoingMessage } = require('_http_outgoing');
|
||||
@ -41,6 +42,9 @@ const {
|
||||
defaultTriggerAsyncIdScope,
|
||||
getOrSetAsyncId
|
||||
} = require('internal/async_hooks');
|
||||
const { IncomingMessage } = require('_http_incoming');
|
||||
|
||||
const kServerResponse = Symbol('ServerResponse');
|
||||
|
||||
const STATUS_CODES = {
|
||||
100: 'Continue',
|
||||
@ -260,9 +264,19 @@ function writeHead(statusCode, reason, obj) {
|
||||
// Docs-only deprecated: DEP0063
|
||||
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 });
|
||||
|
||||
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.shouldKeepAlive = keepAlive;
|
||||
@ -681,5 +695,6 @@ module.exports = {
|
||||
STATUS_CODES,
|
||||
Server,
|
||||
ServerResponse,
|
||||
_connectionListener: connectionListener
|
||||
_connectionListener: connectionListener,
|
||||
kServerResponse
|
||||
};
|
||||
|
@ -30,6 +30,9 @@ const util = require('util');
|
||||
const { inherits } = util;
|
||||
const debug = util.debuglog('https');
|
||||
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) {
|
||||
if (!(this instanceof Server)) return new Server(opts, requestListener);
|
||||
@ -51,9 +54,10 @@ function Server(opts, requestListener) {
|
||||
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) {
|
||||
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