• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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