Got: timeouts not working as expected

Created on 2 Aug 2016  Â·  10Comments  Â·  Source: sindresorhus/got

I'm looking at switching from request to got due to massive amount of bloat. It looks like timeouts don't behave the same way in got and am wondering what the issue is.

Versions: got v6.3.0 on node.js v6.3.1.

This code never terminates :-1:

const got = require('got');

const url = 'http://10.155.155.155';
const options = {
    timeout: 500
};

got(url, options).then(function(res) {
    console.log(res.body);
}).catch(function (err) {
    console.error(err);
})

This code terminates after 500ms :+1:

const rp = require('request-promise');
const rpOptions = {
    'http://10.155.155.155',
    timeout: 500
};

rp(rpOptions).then(function(res) {
    console.log(res.body);
}).catch(function (err) {
    console.error(err);
})
{ RequestError: Error: ETIMEDOUT
    at new RequestError (request-promise/lib/errors.js:11:15)
    at Request.RP$callback [as _callback] (request-promise/lib/rp.js:60:32)
    at self.callback (request/request.js:187:22)
    at emitOne (events.js:96:13)
    at Request.emit (events.js:188:7)
    at Timeout._onTimeout (request/request.js:762:12)
    at tryOnTimeout (timers.js:224:11)
    at Timer.listOnTimeout (timers.js:198:5)
  name: 'RequestError',
  message: 'Error: ETIMEDOUT',
  cause: 
   { Error: ETIMEDOUT
       at Timeout._onTimeout (request/request.js:759:15)
       at tryOnTimeout (timers.js:224:11)
       at Timer.listOnTimeout (timers.js:198:5) code: 'ETIMEDOUT', connect: true },
  error: 
   { Error: ETIMEDOUT
       at Timeout._onTimeout (request/request.js:759:15)
       at tryOnTimeout (timers.js:224:11)
       at Timer.listOnTimeout (timers.js:198:5) code: 'ETIMEDOUT', connect: true },
  options: 
   { url: 'http://10.155.155.155',
     timeout: 500,
     callback: undefined,
     transform: undefined,
     simple: true,
     resolveWithFullResponse: false },
  response: undefined }

Note that the IP is just some garbage IP address that is not assigned to anything. Any help would be appreciated. Thanks!

Most helpful comment

Please write about it in documentation. It's totally unclear.

All 10 comments

I should also note that needle (another minimal HTTP request library I am looking at) does timeouts correctly as well.

This code terminates after 500ms :+1:

// note that I manually promisified this code, which isn't shown
const url = 'http://10.155.155.155';
const options = {
    timeout: 500
};

needle.get(url, options).then(function(res) {
    console.log(res.body);
}).catch(function (err) {
    console.error(err);
})

Output:

{ Error: socket hang up
    at createHangUpError (_http_client.js:252:15)
    at Socket.socketCloseListener (_http_client.js:284:23)
    at emitOne (events.js:101:20)
    at Socket.emit (events.js:188:7)
    at TCP._handle.close [as _onclose] (net.js:492:12) code: 'ECONNRESET' }

@MarkHerhold ETIMEDOUT error is whitelisted for retrying – so setting retries: 0 fixes your issue.

Ah! Novice mistake. Thanks @floatdrop

Please write about it in documentation. It's totally unclear.

Still an issue. Timeout is not respected when it is greater than 1000ms.

const got = require('got');

const url = 'http://10.15.15.234';
const options = {
    timeout: 1000,
    retries: 0
};

got(url, options).then(function(res) {
    console.log(res.body);
}).catch(function (err) {
    console.error(err);
})

Reopening for @pasupulaphani

@pasupulaphani can you tell, what is expected? I've tested this with added console.time and it gives me 1015.766ms before firing error.

@floatdrop Sorry for the false alarm. Looks like I made mistake. Not a bug.

Can you provide a full example how to make timeouts work properly without retries?

The following code takes ~8 secs to run:

const got = require('got');

const url = 'http://10.155.155.155';
const options = {
    timeout: 500,
    retry: 0
};

const t0 = Date.now();
got(url, options).then(function(res) {
    console.log(res.body);
}).catch(function (err) {
    console.error(err);
    console.log("Took " + (Date.now() - t0) + " ms")
})

I've also tried retry: { retries: 0 } and retries: 0 and haven't been able to reduce the timeout.

This gotcha! should be mentioned also in the documentation for timeout - if I say timeout: 1000 I expect it to take max 1 second.

@plaa it's retry and not retries

'use strict';

const { expect } = require('chai');
const net = require('net');
const got  = require('got');

let mockServer;

describe('Patch for request', () => {
  // start mock server
  before((done) => {
    mockServer = net.createServer(() => {
      // Never send a reponse to simulate a timeout
    });
    mockServer.listen(10101, done);
  });

  after((done) => {
    mockServer.close(done);
  });

  it('should return an error after the timeout of 500ms', (done) => {
    const t0 = Date.now();
    got('https://10.155.155.155',{
      timeout: 500,
      retry: 0
    }).catch(err =>  {
      console.log('Took ' + (Date.now() - t0) + ' ms');
      expect(err).to.exist;
      expect(err).to.have.property('code').that.equals('ETIMEDOUT');
      expect(err).to.have.property('message').that.includes('Timeout awaiting \'request\' for 500ms');
      done();
    });
  });

  it('should return an error after the timeout of 500ms', (done) => {
    const t0 = Date.now();
    got('https://10.155.155.155',{
      timeout: 1500,
      retry: 0
    }).catch(err =>  {
      console.log('Took ' + (Date.now() - t0) + ' ms');
      expect(err).to.exist;
      expect(err).to.have.property('code').that.equals('ETIMEDOUT');
      expect(err).to.have.property('message').that.includes('Timeout awaiting \'request\' for 1500ms');
      done();
    });
  });
});

result
Took 525 ms and Took 1501 ms

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lukechu10 picture lukechu10  Â·  3Comments

erfanium picture erfanium  Â·  3Comments

lukehorvat picture lukehorvat  Â·  3Comments

alanzhaonys picture alanzhaonys  Â·  4Comments

alvis picture alvis  Â·  3Comments