首页 > node执行http请求时curl报错

node执行http请求时curl报错

最新node0.12.4,执行http请求,多次请求的时候,底层出错了,出问题的时候报的错误太搞笑了:

看来新版node底层是用curl来做的http请求。

function get(url,params,callback,pool) {
    var options = {
        qs:params
    };
    if (pool) {
        options.pool = pool;
    }
    request.get(url,options,function(error,response,body) {
        parseResponse(url,'',error,response,body,callback);
    });
}
exports.get = get;

代码1 httptest.js

var testhttp = require('../testhttp');
var count = 0;
var keepAliveAgent = require('../Agent.js'); 
var agent = new keepAliveAgent({ maxSockets: 100 }); 
for(var i= 0;i<1000;i++) {
    testhttp.get('http://www.baidu.com',{},function(err,body) {
        console.log(count++, err);
    },agent);
}

代码2 test_get_baidu.js

/**
 * Created by Administrator on 14-4-30.
 */
var http = require('http');
var EventEmitter = require('events').EventEmitter;
var net = require('net');
var util = require('util');

var Agent = function(options)
{
    var self = this;
    // 选项配置
    self.options  = options || {};
    // 保存请求的全部hostname
    self.requests = {};
    // 创建的socket连接数
    self.sockets = {};
    // 未被使用的socket
    self.unusedSockets = {};
    // socket的最大连接数量
    self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets;
    self.on('free',function(socket,host,port){
        var hostname = host + ':' + port;
        // 如果有正在请求的主机
        if(self.requests[hostname] && self.requests[hostname].length)
        {
            self.requests[hostname].shift().onSocket(socket);
        }
        else
        {
            // 如果没有请求数就销毁socket连接并从连接池移除
            if(!self.unusedSockets[hostname])
            {
                self.unusedSockets[hostname] = [];
            }
            self.unusedSockets[hostname].push(socket);
        }
    });
    self.createConnection = net.createConnection;
};
util.inherits(Agent,EventEmitter);

Agent.defaultMaxSockets = 10;

Agent.prototype.defaultPort = 80;

Agent.prototype.addRequest = function(req,host,port)
{
    var hostname = host + ':' + port;
    if(this.unusedSockets[hostname] && this.unusedSockets[hostname].length)
    {
        req.onSocket(this.unusedSockets[hostname].shift());
        return;
    }
    if(!this.sockets[hostname])
    {
        this.sockets[hostname] = [];
    }
    if(this.sockets[hostname].length < this.maxSockets)
    {
        req.onSocket(this.createSocket(hostname,host,port));
    }
    else
    {
        if(!this.requests[hostname])
        {
            this.requests[hostname] = [];
        }
        this.requests[hostname].push(req);
    }
};

Agent.prototype.createSocket = function(name, host, port) {
    var self = this;
    var s = self.createConnection(port, host, self.options);
    if (!self.sockets[name]) {
        self.sockets[name] = [];
    }
    this.sockets[name].push(s);
    var onFree = function() {
        self.emit('free', s, host, port);
    }
    s.on('free', onFree);
    var onClose = function(err) {
        // 这是唯一移除socket代理的地方,如果你想从连接池中移除socket,就关闭连接,所有的socket错误会导致连接关闭
        self.removeSocket(s, name, host, port);
    }
    s.on('close', onClose);
    var onRemove = function() {
        // We need this function for cases like HTTP "upgrade"
        // (defined by WebSockets) where we need to remove a socket from the pool
        //  because it'll be locked up indefinitely
        self.removeSocket(s, name, host, port);
        s.removeListener('close', onClose);
        s.removeListener('free', onFree);
        s.removeListener('agentRemove', onRemove);
    }
    s.on('agentRemove', onRemove);
    return s;
};
Agent.prototype.removeSocket = function(s, name, host, port) {
    if (this.sockets[name]) {
        var index = this.sockets[name].indexOf(s);
        if (index !== -1) {
            this.sockets[name].splice(index, 1);
        }
    } else if (this.sockets[name] && this.sockets[name].length === 0) {
        delete this.sockets[name];
        delete this.requests[name];
    }
    if (this.requests[name] && this.requests[name].length) {
        // If we have pending requests and a socket gets closed a new one
        // needs to be created to take over in the pool for the one that closed.
        this.createSocket(name, host, port).emit('free');
    }
};

module.exports = Agent;

代码3 Agent.js
入口文件是test_get_baidu.js,首先我很诧异node底层竟然使用curl来完成http请求,其次我想知道这个错误可否避免。


curl请求是同步的,而Nodejs的http请求是异步的。
如果在nodejs 中实现curl,也有相关的package

【热门文章】
【热门文章】