Как установить тайм-аут на http.request () в узле?

Я пытаюсь установить таймаут на HTTP-клиент, который использует http.request без везения. Пока что я сделал это:

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

Любые намеки?

С помощью вашего кода проблема в том, что вы не дождались назначения сокета для запроса, прежде чем пытаться установить материал на объект сокета. Это все async так:

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

Событие ‘socket’ запускается, когда запросу присваивается объект сокета.

На данный момент существует способ сделать это непосредственно на объекте запроса:

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

Это метод ярлыков, который привязывается к событию сокета, а затем создает тайм-аут.

Ссылка: Node.js v0.8.8 Руководство и документация

Rob Evans anwser работает правильно для меня, но когда я использую request.abort (), возникает ошибка, связанная с зависанием сокета, которая остается необработанной.

Мне пришлось добавить обработчик ошибок для объекта запроса:

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

Существует более простой метод.

Вместо использования setTimeout или работы с сокетом напрямую,
Мы можем использовать «тайм-аут» в «вариантах» для использования клиентами

Ниже приведен код сервера и клиента, в 3 частях.

Часть модуля и опций:

 '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 }; 

Часть сервера:

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

Клиентская часть:

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

Если вы поместите все вышеуказанные 3 части в один файл, «a.js», а затем запустите:

 node a.js 

то вывод будет:

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

Надеюсь, это поможет.

Для меня – здесь менее запутанный способ сделать 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 ↑ }); }); 

Разрабатывая ответ @douwe здесь, вы должны поместить таймаут в 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 () также отлично.

Вы должны передать ссылку на запрос, как показано ниже.

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

Любопытно, что произойдет, если вместо этого использовать прямые net.sockets ? Вот пример кода, который я собрал для тестирования:

 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(); 
Давайте будем гением компьютера.