¿Cómo establecer un tiempo de espera en http.request () en Node?

Estoy intentando establecer un tiempo de espera en un cliente HTTP que utiliza http.request sin suerte. Hasta ahora lo que hice fue esto:

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(); 

¿Algún consejo?

Usando su código, el problema es que no ha esperado a que se le asigne un socket a la solicitud antes de intentar establecer cosas en el objeto socket. Todo es asínc entonces:

 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(); 

El evento ‘socket’ se dispara cuando a la solicitud se le asigna un objeto socket.

En este momento hay un método para hacer esto directamente en el objeto de solicitud:

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

Este es un método abreviado que se une al evento socket y luego crea el tiempo de espera.

Referencia: Node.js v0.8.8 Manual y documentación

El guante de Rob Evans funciona correctamente para mí, pero cuando uso request.abort (), se produce un error de suspensión del socket que no se controla.

Tuve que agregar un controlador de errores para el objeto de solicitud:

 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(); 

Hay un método más simple.

En lugar de usar setTimeout o trabajar con socket directamente,
Podemos usar ‘timeout’ en las ‘opciones’ en los usos del cliente

A continuación se muestra el código de servidor y cliente, en 3 partes.

Parte del módulo y opciones:

 '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 del 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 del 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(); 

Si coloca todas las 3 partes anteriores en un archivo, “a.js”, y luego ejecuta:

 node a.js 

entonces, la salida 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 ayude.

Para mí, aquí hay una forma menos confusa de hacer el 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 ↑ }); }); 

En la respuesta @douwe aquí es donde pondría un tiempo de espera en una solicitud 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 () también está bien.

Debe pasar la referencia para solicitarla como a continuación

 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, ¿qué pasa si usas net.sockets en net.sockets lugar? Aquí hay un código de muestra que reuní para fines de prueba:

 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();