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'use strict'; 23const common = require('../common'); 24 25if (!common.hasCrypto) 26 common.skip('missing crypto'); 27 28const assert = require('assert'); 29const fixtures = require('../common/fixtures'); 30const https = require('https'); 31const http = require('http'); 32const tls = require('tls'); 33 34const tests = []; 35 36const serverOptions = { 37 key: fixtures.readKey('agent1-key.pem'), 38 cert: fixtures.readKey('agent1-cert.pem') 39}; 40 41function test(fn) { 42 if (!tests.length) 43 process.nextTick(run); 44 tests.push(common.mustCall(fn)); 45} 46 47function run() { 48 const fn = tests.shift(); 49 if (fn) { 50 fn(run); 51 } 52} 53 54test(function serverTimeout(cb) { 55 const server = https.createServer(serverOptions); 56 server.listen(common.mustCall(() => { 57 const s = server.setTimeout(50, common.mustCall((socket) => { 58 socket.destroy(); 59 server.close(); 60 cb(); 61 })); 62 assert.ok(s instanceof https.Server); 63 https.get({ 64 port: server.address().port, 65 rejectUnauthorized: false 66 }).on('error', common.mustCall()); 67 })); 68}); 69 70test(function serverRequestTimeout(cb) { 71 const server = https.createServer( 72 serverOptions, 73 common.mustCall((req, res) => { 74 // Just do nothing, we should get a timeout event. 75 const s = req.setTimeout(50, common.mustCall((socket) => { 76 socket.destroy(); 77 server.close(); 78 cb(); 79 })); 80 assert.ok(s instanceof http.IncomingMessage); 81 })); 82 server.listen(common.mustCall(() => { 83 const req = https.request({ 84 port: server.address().port, 85 method: 'POST', 86 rejectUnauthorized: false 87 }); 88 req.on('error', common.mustCall()); 89 req.write('Hello'); 90 // req is in progress 91 })); 92}); 93 94test(function serverResponseTimeout(cb) { 95 const server = https.createServer( 96 serverOptions, 97 common.mustCall((req, res) => { 98 // Just do nothing, we should get a timeout event. 99 const s = res.setTimeout(50, common.mustCall((socket) => { 100 socket.destroy(); 101 server.close(); 102 cb(); 103 })); 104 assert.ok(s instanceof http.OutgoingMessage); 105 })); 106 server.listen(common.mustCall(() => { 107 https.get({ 108 port: server.address().port, 109 rejectUnauthorized: false 110 }).on('error', common.mustCall()); 111 })); 112}); 113 114test(function serverRequestNotTimeoutAfterEnd(cb) { 115 const server = https.createServer( 116 serverOptions, 117 common.mustCall((req, res) => { 118 // Just do nothing, we should get a timeout event. 119 const s = req.setTimeout(50, common.mustNotCall()); 120 assert.ok(s instanceof http.IncomingMessage); 121 res.on('timeout', common.mustCall()); 122 })); 123 server.on('timeout', common.mustCall((socket) => { 124 socket.destroy(); 125 server.close(); 126 cb(); 127 })); 128 server.listen(common.mustCall(() => { 129 https.get({ 130 port: server.address().port, 131 rejectUnauthorized: false 132 }).on('error', common.mustCall()); 133 })); 134}); 135 136test(function serverResponseTimeoutWithPipeline(cb) { 137 let caughtTimeout = ''; 138 let secReceived = false; 139 process.on('exit', () => { 140 assert.strictEqual(caughtTimeout, '/2'); 141 }); 142 const server = https.createServer(serverOptions, (req, res) => { 143 if (req.url === '/2') 144 secReceived = true; 145 if (req.url === '/1') { 146 res.end(); 147 return; 148 } 149 const s = res.setTimeout(50, () => { 150 caughtTimeout += req.url; 151 }); 152 assert.ok(s instanceof http.OutgoingMessage); 153 }); 154 server.on('timeout', common.mustCall((socket) => { 155 if (secReceived) { 156 socket.destroy(); 157 server.close(); 158 cb(); 159 } 160 })); 161 server.listen(common.mustCall(() => { 162 const options = { 163 port: server.address().port, 164 allowHalfOpen: true, 165 rejectUnauthorized: false 166 }; 167 const c = tls.connect(options, () => { 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 175test(function idleTimeout(cb) { 176 // Test that the an idle connection invokes the timeout callback. 177 const server = https.createServer(serverOptions); 178 const s = server.setTimeout(50, common.mustCall((socket) => { 179 socket.destroy(); 180 server.close(); 181 cb(); 182 })); 183 assert.ok(s instanceof https.Server); 184 server.listen(common.mustCall(() => { 185 const options = { 186 port: server.address().port, 187 allowHalfOpen: true, 188 rejectUnauthorized: false 189 }; 190 const c = tls.connect(options, () => { 191 // ECONNRESET could happen on a heavily-loaded server. 192 c.on('error', (e) => { 193 if (e.message !== 'read ECONNRESET') 194 throw e; 195 }); 196 c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n'); 197 // Keep-Alive 198 }); 199 })); 200}); 201 202test(function fastTimeout(cb) { 203 // Test that the socket timeout fires but no timeout fires for the request. 204 let connectionHandlerInvoked = false; 205 let timeoutHandlerInvoked = false; 206 let connectionSocket; 207 208 function invokeCallbackIfDone() { 209 if (connectionHandlerInvoked && timeoutHandlerInvoked) { 210 connectionSocket.destroy(); 211 server.close(); 212 cb(); 213 } 214 } 215 216 const server = https.createServer(serverOptions, common.mustCall( 217 (req, res) => { 218 req.on('timeout', common.mustNotCall()); 219 res.end(); 220 connectionHandlerInvoked = true; 221 invokeCallbackIfDone(); 222 } 223 )); 224 const s = server.setTimeout(1, common.mustCall((socket) => { 225 connectionSocket = socket; 226 timeoutHandlerInvoked = true; 227 invokeCallbackIfDone(); 228 })); 229 assert.ok(s instanceof https.Server); 230 server.listen(common.mustCall(() => { 231 const options = { 232 port: server.address().port, 233 allowHalfOpen: true, 234 rejectUnauthorized: false 235 }; 236 const c = tls.connect(options, () => { 237 c.write('GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n'); 238 // Keep-Alive 239 }); 240 })); 241}); 242