如何在Node上的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();
任何提示?
使用你的代码,问题是在尝试设置套接字对象的东西之前,你还没有等待一个套接字被分配给请求。 这都是asynchronous的:
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();
当请求分配一个套接字对象时,会触发'套接字'事件。
此时有一种方法直接对请求对象执行此操作:
request.setTimeout(timeout, function() { request.abort(); });
这是绑定到套接字事件,然后创build超时的快捷方法。
参考: Node.js v0.8.8手册和文档
Rob Evans anwser对我来说工作正常,但是当我使用request.abort()时,它会抛出一个socket挂起错误,而这个错误一直处于未处理状态。
我不得不为请求对象添加一个error handling程序:
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.setTimeout(60000, function(){ this.abort(); }.bind(req); req.write('something'); req.end();
对我来说 – 这是一个不太令人困惑的做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 ↑ }); });
好奇,如果你使用直接的net.sockets
,会发生什么? 下面是我为了testing目的而放置的一些示例代码:
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();
有更简单的方法。
而不是使用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!
希望有所帮助。