基于Node.js http-proxy库的本地HTTP代理服务器脚本

此脚本的主要目的:让浏览器客户端首先通过此代理,然后再访问目标网站。可基于特定的url做正则表达式匹配,然后替换为本地修改的版本。

    主要用于浏览器内核研发过程中某些怀疑是特定网站JS脚本执行出错导致的渲染异常bug。可在JS脚本中插入console.log以定位出错点。

var ProxyPort = 8888;

var http = require('http'),
    net = require('net'),
    url = require('url'),
    httpProxy = require('http-proxy'); //需要执行npm install http-proxy --save

var proxy = httpProxy.createProxyServer({
    autoRewrite: true, //??
});

proxy.on('error', function (err, req, res) {
  res.writeHead(500, {
    'Content-Type': 'text/plain'
  });
  res.end('httpProxy代理请求发生IO错误:URL='+req.url);
});

//支持http CONNECT协议的https代理:(当然,修改不了https连接的内容)
function connect(cReq, cSock) {
    console.log("CONNECT: cReq.url="+cReq.url);
    var u = url.parse('http://' + cReq.url);
    var pSock = net.connect(u.port||80, u.hostname, function() {
        cSock.write('HTTP/1.1 200 Connection Established\r\n\r\n');
        pSock.pipe(cSock);
    }).on('error', function(e) {
        console.log("CONNECT: error! "+e);
        cSock.end();
    });
    cSock.pipe(pSock);
}

var server = http.createServer();
server.on('request', function(req, res) {
    console.log("REQUEST req.url=" + req.url);
    var u = url.parse(req.url);
    //console.log("req.url-parsed.path=" + u.path); //u.path包含了查询参数,而u.pathname不包含 
    //console.log("REQUEST u="+JSON.stringify(u));
    if (u.hostname=="hm.baidu.com" && u.pathname.match(/h.js$/)){
        res.writeHead(500, {
            'Connection': 'close',
            'Content-Type': 'application/x-javascript'
          });
        res.end('');
        //TODO:把特定的js文件的请求重定向到本地的文件服务器,并提供修改后的版本
        //proxy.web(req, res, { target: 'http://127.0.0.1:9999/hm.baidu.com/modified_h.js' });
    }else{
        proxy.web(req, res, {
            target: req.url, //needs apply patch https://github.com/gagern/node-http-proxy/commit/35000fc0d7dc0a6073ac37db097b73575a861d34
            prependPath: false,
            secure: false
        });
        //问题:许多网站无法正常打开,难道是请求头部http-proxy没有正确设置?这个库真的很垃圾
        //Fixed:把target换成forward就可以,可能target就是用来转发请求到本地的资源修改版本的服务器的?但是为什么target选项删除了request headers呢?
    }
}).on('connect', connect)
.on('error', function(err){
    //这里error应该是客户端浏览器到代理脚本之间的连接
    console.log("客户端连接错误: "+JSON.stringify(err));
});

console.log("node-proxy-server: listening on port "+ProxyPort)
server.listen(ProxyPort);

一开始按照正常的target配置不成功,csdn博客文章无法访问,cnblogs文章出现不停重定向,本来还以为是http-proxy不支持chunked-encoding,却原来只是默认prependPath选项被设置为true的缘故。
prependPath: false; //默认是true,导致不正常的处理

你可能感兴趣的:(WebKit,程序员心得体会,读书笔记)