Como definir um tempo limite em um http.request () no nó?

Eu estou tentando definir um tempo limite em um cliente HTTP que usa http.request sem sorte. Até agora o que eu fiz é isso:

var options = { ... } var req = http.request(options, function(res) { // Usual stuff: on(data), on(end), chunks, etc... } /* This does not work TOO MUCH... sometimes the socket is not ready (undefined) expecially on rapid sequences of requests */ req.socket.setTimeout(myTimeout); req.socket.on('timeout', function() { req.abort(); }); req.write('something'); req.end(); 

Alguma dica?

Usando seu código, o problema é que você não esperou que um soquete fosse atribuído à requisição antes de tentar setar coisas no object de soquete. Tudo é asynchronous assim:

 var options = { ... } var req = http.request(options, function(res) { // Usual stuff: on(data), on(end), chunks, etc... }); req.on('socket', function (socket) { socket.setTimeout(myTimeout); socket.on('timeout', function() { req.abort(); }); }); req.on('error', function(err) { if (err.code === "ECONNRESET") { console.log("Timeout occurs"); //specific error treatment } //other error treatment }); req.write('something'); req.end(); 

O evento ‘socket’ é acionado quando o pedido é atribuído a um object de soquete.

Neste momento, há um método para fazer isso diretamente no object de solicitação:

 request.setTimeout(timeout, function() { request.abort(); }); 

Este é um método de atalho que se liga ao evento de soquete e, em seguida, cria o tempo limite.

Referência: Node.js v0.8.8 Manual & Documentation

O rob Evans anwser funciona corretamente para mim, mas quando eu uso request.abort (), ocorre para lançar um erro de desligamento de soquete que permanece sem tratamento.

Eu tive que adicionar um manipulador de erro para o object de solicitação:

 var options = { ... } var req = http.request(options, function(res) { // Usual stuff: on(data), on(end), chunks, etc... } req.on('socket', function (socket) { socket.setTimeout(myTimeout); socket.on('timeout', function() { req.abort(); }); } req.on('error', function(err) { if (err.code === "ECONNRESET") { console.log("Timeout occurs"); //specific error treatment } //other error treatment }); req.write('something'); req.end(); 

Existe um método mais simples.

Em vez de usar setTimeout ou trabalhar com soquete diretamente,
Podemos usar ‘timeout’ nas ‘opções’ em usos do cliente

Abaixo está o código do servidor e do cliente, em 3 partes.

Módulo e parte de opções:

 'use strict'; // Source: https://github.com/nodejs/node/blob/master/test/parallel/test-http-client-timeout-option.js const assert = require('assert'); const http = require('http'); const options = { host: '127.0.0.1', // server uses this port: 3000, // server uses this method: 'GET', // client uses this path: '/', // client uses this timeout: 2000 // client uses this, timesout in 2 seconds if server does not respond in time }; 

Parte do servidor:

 function startServer() { console.log('startServer'); const server = http.createServer(); server .listen(options.port, options.host, function () { console.log('Server listening on http://' + options.host + ':' + options.port); console.log(''); // server is listening now // so, let's start the client startClient(); }); } 

Parte do cliente:

 function startClient() { console.log('startClient'); const req = http.request(options); req.on('close', function () { console.log("got closed!"); }); req.on('timeout', function () { console.log("timeout! " + (options.timeout / 1000) + " seconds expired"); // Source: https://github.com/nodejs/node/blob/master/test/parallel/test-http-client-timeout-option.js#L27 req.destroy(); }); req.on('error', function (e) { // Source: https://github.com/nodejs/node/blob/master/lib/_http_outgoing.js#L248 if (req.connection.destroyed) { console.log("got error, req.destroy() was called!"); return; } console.log("got error! ", e); }); // Finish sending the request req.end(); } startServer(); 

Se você colocar todas as 3 partes acima em um arquivo, “a.js”, e então execute:

 node a.js 

então, a saída será:

 startServer Server listening on http://127.0.0.1:3000 startClient timeout! 2 seconds expired got closed! got error, req.destroy() was called! 

Espero que ajude.

Para mim – aqui está uma maneira menos confusa de fazer o socket.setTimeout

 var request=require('https').get( url ,function(response){ var r=''; response.on('data',function(chunk){ r+=chunk; }); response.on('end',function(){ console.dir(r); //end up here if everything is good! }); }).on('error',function(e){ console.dir(e.message); //end up here if the result returns an error }); request.on('error',function(e){ console.dir(e); //end up here if a timeout }); request.on('socket',function(socket){ socket.setTimeout(1000,function(){ request.abort(); //causes error event ↑ }); }); 

Elaborando a resposta @douwe aqui é onde você colocaria um tempo limite em uma solicitação http.

 // TYPICAL REQUEST var req = https.get(http_options, function (res) { var data = ''; res.on('data', function (chunk) { data += chunk; }); res.on('end', function () { if (res.statusCode === 200) { /* do stuff with your data */} else { /* Do other codes */} }); }); req.on('error', function (err) { /* More serious connection problems. */ }); // TIMEOUT PART req.setTimeout(1000, function() { console.log("Server connection timeout (after 1 second)"); req.abort(); }); 

this.abort () também está bem.

Você deve passar a referência para solicitar como abaixo

 var options = { ... } var req = http.request(options, function(res) { // Usual stuff: on(data), on(end), chunks, etc... }); req.setTimeout(60000, function(){ this.abort(); }).bind(req); req.write('something'); req.end(); 

Curioso, o que acontece se você usar straight.sockets em vez disso? Aqui está um código de exemplo que eu coloquei para fins de teste:

 var net = require('net'); function HttpRequest(host, port, path, method) { return { headers: [], port: 80, path: "/", method: "GET", socket: null, _setDefaultHeaders: function() { this.headers.push(this.method + " " + this.path + " HTTP/1.1"); this.headers.push("Host: " + this.host); }, SetHeaders: function(headers) { for (var i = 0; i < headers.length; i++) { this.headers.push(headers[i]); } }, WriteHeaders: function() { if(this.socket) { this.socket.write(this.headers.join("\r\n")); this.socket.write("\r\n\r\n"); // to signal headers are complete } }, MakeRequest: function(data) { if(data) { this.socket.write(data); } this.socket.end(); }, SetupRequest: function() { this.host = host; if(path) { this.path = path; } if(port) { this.port = port; } if(method) { this.method = method; } this._setDefaultHeaders(); this.socket = net.createConnection(this.port, this.host); } } }; var request = HttpRequest("www.somesite.com"); request.SetupRequest(); request.socket.setTimeout(30000, function(){ console.error("Connection timed out."); }); request.socket.on("data", function(data) { console.log(data.toString('utf8')); }); request.WriteHeaders(); request.MakeRequest();