Node.js实现简单代理服务器

先看下陆凌牛老师的《Node.js权威指南》(2014年4月出版)中的一段代码:

var http=require('http');
var url=require('url');
var server=http.createServer(function(sreq,sres){
    var url_parts=url.parse(sreq.url);
    var opts={
        host:'www.jd.com',
        port:80,
        path:url_parts.pathname,
        headers:sreq.headers
    };
    var creq=http.get(opts,function(cres){
        sres.writeHead(cres.statusCode,cres.headers);
        cres.pipe(sres);
    });
    sreq.pipe(creq);
});
server.listen(8080);

在终端下使用node命令运行,然后网页上输入http://localhost:8080,网页显示如下:

抓狂一番,不知为何,然后冷静下来开始调试代码,既然网页反馈的信息就是请求的URL未找到,那就从此下手,添加以下两行代码查看get方法返回的http.IncomingMessage对象cres信息:

    var creq=http.get(opts,function(cres){
        console.log(cres.statusCode);
        console.log(cres.headers);

        sres.writeHead(cres.statusCode,cres.headers);
        cres.pipe(sres);
    });

重新操作,终端输出如下:

Node.js实现简单代理服务器_第1张图片

代码404说明网页未找到,说明我们的请求URL有问题,至于cres.headers对象信息看起来好像没有什么异常,既然404,那么我就查看下get方法中options对象的headers属性信息,增加一段代码    console.log(opts.headers);,重新运行程序:

Node.js实现简单代理服务器_第2张图片

从终端输出的结果来看就奇怪了,options对象属性headers对象的host属性值为'localhost:8080',也就是说服务器本身向自己开放的服务和端口请求数据,我们明明在代码中指明options对象host属性值为’www.jd.com‘为什么在属性headers中host属性值为‘localhost:8080’,其中Node.js的在这点上的工作原理我是不太清楚,但能肯定的是问题就出现在这里,也就是说两个host属性冲突导致的,可是从客户端发出的sreq.headers信息(即网页中输入地址http://localhost:8080)又不能改变,那我们接着测试,首先把options对象中的headers赋值语句给注释掉,看下执行结果:

Node.js实现简单代理服务器_第3张图片

Node.js实现简单代理服务器_第4张图片

可以看出代理服务器成功运行,到了这里,我觉得问题还没有结束,问题是解决了,但到底其中的原理如何还是不太了解,我们继续做测试,在上步的代码中取消对options对象中headers行的注释,我们查看下get方法返回的http.ClientRequest对象信息,由于输入篇幅太长,这里只截取有用的部分:

Node.js实现简单代理服务器_第5张图片

从中可以看出请求的主机为localhost:8080,而并非www.jd.com,如果headers行加上注释,则显示请求的主机为www.jd.com,如下:

从测试结果可以看出,当options对象的host属性和options对象的headers属性对象中的host起冲突时,Node.js以headers对象中的host属性值为准,找到问题的根源才是最重要的,值得高兴一把。

另外不太理解书中为什么要加入sreq.pipe(creq)这行,本身两个就不是同一个类型的对象,sreq是http.IncomingMessage类型的对象,creq是http.ClientRquest类型的对象,而且从自己另外测试输出的结果来看两个对象相差甚远,另外这句代码如果加上注释不影响测试的结果(代理依然成功),真心不明白这句话的意思,如果单从逻辑上也说不通啊,creq是get函数返回的对象,它是一个结果,而且这个结果本身不会作为其它函数的参数调用,对这样一个结果值再进行任何类似赋值的操作有意义吗?本人刚开始学Node.js,才疏学浅,如果有哪位大牛了解我的疑问,还请帮忙解答一番,小弟这里感激不尽。

需要额外说明的是,我写这篇文章并没有黑陆老师的意思,毕竟Node也是在不断更新,有很多不匹配的地方真的太正常不过了,我的重点是鼓励大家在碰到问题的时候勤于思考,俗话说的好,尽信书则不如无书,尤其在IT领域,更新太快,在这里我还是非常感谢陆老师的这本书。

你可能感兴趣的:(Node.js)