此脚本的主要目的:让浏览器客户端首先通过此代理,然后再访问目标网站。可基于特定的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);
prependPath: false; //默认是true,导致不正常的处理