Skip to content

Commit ab518e8

Browse files
committed
https: implement https.Server#setTimeout()
Like commit d258fb0 ("http: More useful setTimeout API on server") but this time for the https module. Fixes nodejs#5361.
1 parent c081809 commit ab518e8

3 files changed

Lines changed: 221 additions & 2 deletions

File tree

doc/api/https.markdown

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ separate module.
1010
This class is a subclass of `tls.Server` and emits events same as
1111
`http.Server`. See `http.Server` for more information.
1212

13+
### server.setTimeout(msecs, callback)
14+
15+
See [http.Server#setTimeout()][].
16+
17+
### server.timeout
18+
19+
See [http.Server#timeout][].
20+
1321
## https.createServer(options, [requestListener])
1422

1523
Returns a new HTTPS web server object. The `options` is similar to
@@ -197,6 +205,8 @@ for more information.
197205

198206
Global instance of [https.Agent][] for all HTTPS client requests.
199207

208+
[http.Server#setTimeout()]: http.html#http_server_settimeout_msecs_callback
209+
[http.Server#timeout]: http.html#http_server_timeout
200210
[Agent]: #https_class_https_agent
201211
[globalAgent]: #https_https_globalagent
202212
[http.listen()]: http.html#http_server_listen_port_hostname_backlog_callback

lib/https.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,13 @@ function Server(opts, requestListener) {
4343
this.addListener('clientError', function(err, conn) {
4444
conn.destroy(err);
4545
});
46+
47+
this.timeout = 2 * 60 * 1000;
4648
}
4749
inherits(Server, tls.Server);
48-
49-
5050
exports.Server = Server;
5151

52+
Server.prototype.setTimeout = http.Server.prototype.setTimeout;
5253

5354
exports.createServer = function(opts, requestListener) {
5455
return new Server(opts, requestListener);
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
var common = require('../common.js');
23+
var assert = require('assert');
24+
var https = require('https');
25+
var tls = require('tls');
26+
var fs = require('fs');
27+
28+
var tests = [];
29+
30+
var serverOptions = {
31+
key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
32+
cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem')
33+
};
34+
35+
function test(fn) {
36+
if (!tests.length)
37+
process.nextTick(run);
38+
tests.push(fn);
39+
}
40+
41+
function run() {
42+
var fn = tests.shift();
43+
if (fn) {
44+
console.log('# %s', fn.name);
45+
fn(run);
46+
} else
47+
console.log('ok');
48+
}
49+
50+
test(function serverTimeout(cb) {
51+
var caughtTimeout = false;
52+
process.on('exit', function() {
53+
assert(caughtTimeout);
54+
});
55+
var server = https.createServer(serverOptions, function(req, res) {
56+
// just do nothing, we should get a timeout event.
57+
});
58+
server.listen(common.PORT);
59+
server.setTimeout(50, function(socket) {
60+
caughtTimeout = true;
61+
socket.destroy();
62+
server.close();
63+
cb();
64+
});
65+
https.get({
66+
port: common.PORT,
67+
rejectUnauthorized: false
68+
}).on('error', function() {});
69+
});
70+
71+
test(function serverRequestTimeout(cb) {
72+
var caughtTimeout = false;
73+
process.on('exit', function() {
74+
assert(caughtTimeout);
75+
});
76+
var server = https.createServer(serverOptions, function(req, res) {
77+
// just do nothing, we should get a timeout event.
78+
req.setTimeout(50, function() {
79+
caughtTimeout = true;
80+
req.socket.destroy();
81+
server.close();
82+
cb();
83+
});
84+
});
85+
server.listen(common.PORT);
86+
var req = https.request({
87+
port: common.PORT,
88+
method: 'POST',
89+
rejectUnauthorized: false
90+
});
91+
req.on('error', function() {});
92+
req.write('Hello');
93+
// req is in progress
94+
});
95+
96+
test(function serverResponseTimeout(cb) {
97+
var caughtTimeout = false;
98+
process.on('exit', function() {
99+
assert(caughtTimeout);
100+
});
101+
var server = https.createServer(serverOptions, function(req, res) {
102+
// just do nothing, we should get a timeout event.
103+
res.setTimeout(50, function() {
104+
caughtTimeout = true;
105+
res.socket.destroy();
106+
server.close();
107+
cb();
108+
});
109+
});
110+
server.listen(common.PORT);
111+
https.get({
112+
port: common.PORT,
113+
rejectUnauthorized: false
114+
}).on('error', function() {});
115+
});
116+
117+
test(function serverRequestNotTimeoutAfterEnd(cb) {
118+
var caughtTimeoutOnRequest = false;
119+
var caughtTimeoutOnResponse = false;
120+
process.on('exit', function() {
121+
assert(!caughtTimeoutOnRequest);
122+
assert(caughtTimeoutOnResponse);
123+
});
124+
var server = https.createServer(serverOptions, function(req, res) {
125+
// just do nothing, we should get a timeout event.
126+
req.setTimeout(50, function(socket) {
127+
caughtTimeoutOnRequest = true;
128+
});
129+
res.on('timeout', function(socket) {
130+
caughtTimeoutOnResponse = true;
131+
});
132+
});
133+
server.on('timeout', function(socket) {
134+
socket.destroy();
135+
server.close();
136+
cb();
137+
});
138+
server.listen(common.PORT);
139+
https.get({
140+
port: common.PORT,
141+
rejectUnauthorized: false
142+
}).on('error', function() {});
143+
});
144+
145+
test(function serverResponseTimeoutWithPipeline(cb) {
146+
var caughtTimeout = '';
147+
process.on('exit', function() {
148+
assert.equal(caughtTimeout, '/2');
149+
});
150+
var server = https.createServer(serverOptions, function(req, res) {
151+
res.setTimeout(50, function() {
152+
caughtTimeout += req.url;
153+
});
154+
if (req.url === '/1') res.end();
155+
});
156+
server.on('timeout', function(socket) {
157+
socket.destroy();
158+
server.close();
159+
cb();
160+
});
161+
server.listen(common.PORT);
162+
var options = {
163+
port: common.PORT,
164+
allowHalfOpen: true,
165+
rejectUnauthorized: false
166+
};
167+
var c = tls.connect(options, function() {
168+
c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n');
169+
c.write('GET /2 HTTP/1.1\r\nHost: localhost\r\n\r\n');
170+
c.write('GET /3 HTTP/1.1\r\nHost: localhost\r\n\r\n');
171+
});
172+
});
173+
174+
test(function idleTimeout(cb) {
175+
var caughtTimeoutOnRequest = false;
176+
var caughtTimeoutOnResponse = false;
177+
var caughtTimeoutOnServer = false;
178+
process.on('exit', function() {
179+
assert(!caughtTimeoutOnRequest);
180+
assert(!caughtTimeoutOnResponse);
181+
assert(caughtTimeoutOnServer);
182+
});
183+
var server = https.createServer(serverOptions, function(req, res) {
184+
req.on('timeout', function(socket) {
185+
caughtTimeoutOnRequest = true;
186+
});
187+
res.on('timeout', function(socket) {
188+
caughtTimeoutOnResponse = true;
189+
});
190+
res.end();
191+
});
192+
server.setTimeout(50, function(socket) {
193+
caughtTimeoutOnServer = true;
194+
socket.destroy();
195+
server.close();
196+
cb();
197+
});
198+
server.listen(common.PORT);
199+
var options = {
200+
port: common.PORT,
201+
allowHalfOpen: true,
202+
rejectUnauthorized: false
203+
};
204+
tls.connect(options, function() {
205+
this.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n');
206+
// Keep-Alive
207+
});
208+
});

0 commit comments

Comments
 (0)