-
-
Save ishiduca/2280639 to your computer and use it in GitHub Desktop.
| var events,http, url, path; | |
| events = require('events'); | |
| http = require('http'); | |
| url = require('url'); | |
| path = require('path'); | |
| var agents = {}; | |
| agent.onSocketsLengthChange; | |
| if (http.getAgent) { | |
| agents.onSocketsLengthChange = function (agent) { | |
| var helper; | |
| while (agent.sockets.length < agent.maxSockets && agent.waitRequests.length > 0) { | |
| helper = agent.waitRequests.shift(); | |
| helper(); | |
| } | |
| agent.sockets.forEach(function (socket, i) { | |
| if (! socket.hasOnCloseListener) { | |
| socket.hasOnCloseListener = 1; | |
| socket.once('close', function (had_error) { | |
| if (had_error) { | |
| console.log('sockets[' + i + '/' + agent.sockets.length + '] is closing by error'); | |
| } | |
| agents.onSocketsLengthChange(agent); | |
| }); | |
| console.log('set agent.sockets[' + i + '] "hasOnCloseListener"'); | |
| } | |
| }); | |
| }; | |
| } | |
| function httpRequest (/* getURL, method, options, onResponse */) { | |
| var that, agentid, helper, | |
| args, getURL, uri, uriPath, method, options, headers, body, requestOptions; | |
| that = this; | |
| args = Array.prototype.slice.apply(arguments); | |
| getURL = args.shift(); | |
| onResponse = args.pop(); | |
| method = args.shift() || 'GET'; | |
| method = method.toUpperCase(); | |
| options = args.shift() || {}; | |
| if (options.body) { | |
| body = options.body || null; | |
| delete options.body; | |
| } | |
| headers = options; | |
| uri = url.parse(getURL()); | |
| uriPath = (! uri.pathname) ? '/' | |
| : (uri.pathname.slice(0, 1) === '/') ? uri.pathname | |
| : '/' + uri.pathname; | |
| if (uri.search) uriPath += uri.search; | |
| if (method === 'POST') { | |
| headers['content-type'] = headers['content-type'] || 'application/x-www-form-urlencoded'; | |
| headers['content-length'] = (body) ? Buffer.byteLength(body) : 0; | |
| } | |
| if (! headers.referer && this.referer) headers.referer = this.referer; | |
| if (! headers.cookie && this.cookie) headers.cookie = this.cookie; | |
| requestOptions = { | |
| method : method, | |
| host : uri.host, | |
| port : (uri.port) ? uri.port : (uri.protocol === 'https') ? '443' : '80', | |
| path : uriPath, | |
| headers : headers | |
| }; | |
| helper = function () { | |
| var req; | |
| req = http.request(requestOptions); | |
| req.on('error', function (error) { | |
| console.log(error); | |
| process.exit(1); | |
| }); | |
| req.on('response', function (response) { | |
| var statusCode, responseHeaders, _onResponse; | |
| statusCode = response.statusCode; | |
| responseHeaders = response.headers; | |
| if (responseHeaders['set-cookie']) that.cookie = responseHeaders['set-cookie'][0]; | |
| that.referer = uri.href; | |
| if (that.redirect && statusCode >= 300 && statusCode < 400 && responseHeaders.location) { | |
| _onResponse = onResponse; | |
| httpRequest( | |
| function () { return responseHeaders.location; }, 'GET', | |
| { referer : that.referer, cookie : that.cookie }, | |
| function (response, request) { | |
| _onResponse(response, request); | |
| } | |
| ) | |
| return; | |
| } | |
| onResponse(response, [ uri.href, headers, body ]); | |
| }); | |
| if (body) req.write(body); | |
| req.end(); | |
| }; | |
| if (agents.onSocketsLengthChange) { | |
| agentid = [ requestOptions.host, requestOptions.port ].join(':'); | |
| if (! agents[agentid]) { | |
| agents[agentid] = http.getAgent(requestOptions.host, requestOptions.port); | |
| agents[agentid].waitRequests = []; | |
| agents[agentid].maxSockets = 2; | |
| } | |
| agents[agentid].waitRequests.push(helper); | |
| agents.onSocketsLengthChange(agents[agentid]); | |
| return; | |
| } | |
| helper(); | |
| } | |
| exports.httpRequest = httpRequest; |
勉強になりました。助かりました、ありがとうございます。
var httpRequest = function(/* getURL, method, options, onResponse */)
{
//..
}
のほうが良いように思います。WebStormでは、コンスタントなバリューをエクスポートしようとしているというエラーがでました。
kenokabe
ご指摘ありがとうございます。
WebStrom は使ったことなかったので見直したいと思います。
どういたしまして、
あと、どうしてもわからないので、教えていただきたいのですが、
Cannot read property 'onSocketsLengthChange' of undefined
という例外がでまして、
それは多分agentがundefinedなのだと思いますが、
特に、ライブラリの
var agents;
if (http.getAgent) {
agents = {};
agents.onSocketsLengthChange = function (agent) {
......
の部分は、
続くダウンローダーサンプルのように、
httpRequest = require('./httpclient').httpRequest;
としても、けしてリーチできないブロックにあるのではないでしょうか?
node のバージョンはなんでしょうか?
v0.4.12 では agents.onSocketsLengthChange は正常に呼び出されてるんで、なんだろう...
追記:
バグでした。直しました。
v0.6.17(現時点で最新のバージョン)です。
IRCでこの辺よくわからず質問したところ、このバージョンでhttp周りのメモリリークなど多くの改善がされているようです。
修正どうもありがとうございました。
こちらこそ勉強になりました
8行目の
var agents;
の所で、 agents が定義されていないのが問題だったので
var agents = {};
agents.onSocketsLengthChange;
とすることでバグを回避しました。
実際の所、古いバージョンを使わない限り agent 周りは弄る必要がないので、不要な部分は削除していいと思います
ということなので、v5.3+ だとこんな処理の必要がない
追記: v5.3+ 以上でもエラーが起きないように対応した 2012.04.03