connectTimeout doesn't work, request hangs forever

51 views
Skip to first unread message

Alexey Komarov

unread,
Dec 22, 2016, 5:30:59 PM12/22/16
to restify, ale...@komarov.org.ru
Hello,

If I create restifyClient and then do 3 requests to a server 
without closing the client, connectTimeout doesn't work and the call hangs 
for a long time (~20 minutes).

To illustrate the issue I wrote a small script which is attached.
It's a bit nasty and requires sudo but it's simple and can be run on linux without
any remote server. However, this also can be reproduced with a remote server,
if you put local or remote interface down after the second request.

Could someone explain why connectTimeout doesn't work here?

const restify = require('restify');
const assert = require('assert');
const exec = require('child_process').exec;

var server = restify.createServer();
var myIf = 'eth0:1';

function ifUp(cb) {
   
exec('ifconfig ' + myIf + ' 192.168.32.1', function(err) {
       
assert(!err);
        cb
();
   
});
}

function ifDown(cb) {
   
exec('ifconfig ' + myIf + ' down', function(err) {
       
assert(!err);
        cb
();
   
});
}

function serverUp(cb) {
    server
.get('/', function (req, res, next) {
        res
.send('foo');
       
next();
   
});

    server
.listen(7777, cb);
}

function prepare(cb) {
    ifUp
(function() {
        serverUp
(cb);
   
});
}

var client = restify.createStringClient({
    url
: 'http://192.168.32.1:7777',
    connectTimeout
: 3000,
    requestTimeout
: 3000,
    version
: '*',
   
retry: false
});

prepare
(function() {
    console
.log('request 1');

    client
.get('/', function(err, req, res, data)  {
       
assert(!err);

        console
.log('request 2');
        client
.get('/', function(err, req, res, data) {
           
assert(!err);

            ifDown
(function() {
                console
.log("request 3", new Date());

                client
.get('/', function(err, req, res, data) {
                    console
.log("done", new Date());
                    console
.log(err);
               
});
           
});
       
});
   
});
});

Thanks,
Alexey Komarov

Alexey Komarov

unread,
Dec 23, 2016, 10:53:10 AM12/23/16
to restify, ale...@komarov.org.ru
I think I'm starting to understand,
the problem is here:
https://github.com/restify/node-restify/blob/4.x/lib/clients/http_client.js#L223

When I do third and further requests, requestTimeout is just not set.
For second request it's set because _socket._connecting == true (I don't understand why)
But when I do third and further requests, _socket._connecting == false, so requestTimeout is not set.

This can be easily reproduced on any OS, all you need is just a simple HTTP server which replies with a delay (e.g. 10 sec).
Simplified script:
const restify = require('restify');
const assert = require('assert');
const exec = require('child_process').exec;

var server = restify.createServer();

var i = 0;

server.get('/', function (req, res, next) {
    if (i++) {
        setInterval(function() {
            res.send('bar');
            next();
        }, 10000);

        return;
    }

    res.send('foo');
    next();
});

server.listen(7777, function() {
    console.log('server started');
});


var client = restify.createStringClient({
    url: 'http://127.0.0.1:7777',
    connectTimeout: 3000,
    requestTimeout: 3000,
    version: '*',
    retry: false
});

console.log('request 1');

client.get('/', function(err, req, res, data)  {
    assert(!err);

    console.log('request 2', new Date());
    client.get('/', function(err, req, res, data) {
        console.log("done", new Date());
        console.log(err);

        console.log('request 3', new Date());
        client.get('/', function(err, req, res, data) {
            console.log("done", new Date());
            console.log(err);
        });
    });
});


Third request waits for 10 seconds despite reqestTimeout which I set when created the client.
Reply all
Reply to author
Forward
0 new messages