Я пытаюсь установить тайм-аут на 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();
Есть подсказки?
Ответы:
Просто чтобы прояснить ответ выше :
Теперь можно использовать
timeout
опцию и соответствующее событие запроса:// set the desired timeout in options const options = { //... timeout: 3000, }; // create a request const request = http.request(options, response => { // your callback here }); // use its "timeout" event to abort the request request.on('timeout', () => { request.abort(); });
источник
setTimeout(req.abort.bind(req), 3000);
connect
тайм-аут, как только сокет установлен, он не действует. Так что это не поможет серверу, который слишком долго держит сокет открытым (вам все равно нужно будет свернуть свой собственный с помощью setTimeout).timeout : A number specifying the socket timeout in milliseconds. This will set the timeout before the socket is connected.
request.destroy
(abort
устарел.) Кроме того, это отличается отsetTimeout
Обновление 2019
Теперь есть несколько способов сделать это более элегантно. Пожалуйста, посмотрите другие ответы в этой теме. Технологии развиваются быстро, поэтому ответы часто довольно быстро устаревают. Мой ответ все равно будет работать, но стоит также поискать альтернативы.
2012 Ответ
При использовании вашего кода проблема заключается в том, что вы не дождались назначения сокета запросу, прежде чем пытаться установить что-то в объекте сокета. Это все асинхронно, так что:
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();
Событие «сокет» запускается, когда запросу назначается объект сокета.
источник
req.abort()
на данный момент не кажется стандартной функциональностью. Следовательно,socket.on
вы можете захотеть установить такую переменную,timeout = true
а затем соответствующим образом обработать тайм-аут в обработчике ответаНа данный момент есть способ сделать это непосредственно с объектом запроса:
request.setTimeout(timeout, function() { request.abort(); });
Это метод ярлыка, который связывается с событием сокета и затем создает тайм-аут.
Ссылка: Node.js v0.8.8 Руководство и документация
источник
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();
источник
myTimeout
функция? (редактировать: в документах говорится: То же, что и привязка к событию тайм-аута nodejs.org/api/… )ECONNRESET
может произойти в обоих случаях: клиент закрывает сокет, а сервер закрывает соединение. Чтобы определить, сделал ли это клиент по телефону,abort()
есть особоеabort
событиеЕсть способ попроще.
Вместо использования 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», а затем запустите:
тогда вывод будет:
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();
Будет запущено событие ошибки запроса
req.on("error", function(e){ console.log("Request Error : "+JSON.stringify(e)); });
источник
Любопытно, что будет, если
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();
источник