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