Skip to content

Instantly share code, notes, and snippets.

@shuhei
Last active May 14, 2017 17:24
Show Gist options
  • Save shuhei/3d8bbd80150a75aaaa60f5006c31e3ed to your computer and use it in GitHub Desktop.
Save shuhei/3d8bbd80150a75aaaa60f5006c31e3ed to your computer and use it in GitHub Desktop.
Node.js http.request timeout
const net = require('net');
const dns = require('dns');
const http = require('http');
const start = Date.now();
function log() {
const time = (Date.now() - start).toString();
console.log.apply(console, [time].concat(Array.from(arguments)));
}
function delay(func, msecs) {
return function () {
const args = arguments;
setTimeout(() => {
func.apply(this, args);
}, msecs);
};
}
function isRequestEnd(str) {
const len = str.length;
if (len < 4) {
return false;
}
return str[len - 4] === '\r' &&
str[len - 3] === '\n' &&
str[len - 2] === '\r' &&
str[len - 1] === '\n';
}
const server = net.createServer((socket) => {
let buffer = '';
socket.setEncoding('utf8');
socket.on('data', (chunk) => {
buffer += chunk;
if (isRequestEnd(buffer)) {
log('[server]', buffer);
setTimeout(() => {
socket.write('HTTP/1.1 200 OK\r\n');
setTimeout(() => {
socket.write('Content-Length: 5\r\n');
socket.write('\r\n');
socket.write('hello');
socket.end();
}, 200);
}, 200);
}
});
});
server.listen(() => {
const port = server.address().port;
log('[server] Listening on', port);
// Don't specify `path` with `createConnection` because it tries to
// connect to the domain socket specified by the `path`.
const req = http.request({
port: port,
// Cannot have delay on net.createConnection easily because it has to return
// a socket synchronously.
// createConnection: net.createConnection,
lookup: delay(dns.lookup, 200),
// timeout: 250,
timeout: 150,
}, (res) => {
log('[client]', res.statusCode, res.headers);
let buffer = '';
res.setEncoding('utf8');
res.on('data', (chunk) => {
buffer += chunk;
});
res.once('end', () => {
log('[client]', buffer);
server.close();
});
});
req.once('error', (e) => {
log('[client] error:', e);
});
req.on('timeout', () => {
log('[client] timeout');
});
req.end();
log('[client] making request');
});

150 ms timeout

timeout event was emitted only once even though there were 3 chances for timeout.

$ node http-request.js
8 [server] Listening on 53190
23 [client] making request
174 [client] timeout
234 [server] GET / HTTP/1.1
Host: localhost:53190
Connection: close


646 [client] 200 { 'content-length': '5' }
652 [client] hello

250 ms timeout

No timeout event was emitted even though the overall request/response took more than 600 ms.

$ node http-request.js
9 [server] Listening on 53226
21 [client] making request
231 [server] GET / HTTP/1.1
Host: localhost:53226
Connection: close


639 [client] 200 { 'content-length': '5' }
644 [client] hello
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment