Skip to content

Instantly share code, notes, and snippets.

@chiral
Created December 4, 2013 10:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chiral/7785784 to your computer and use it in GitHub Desktop.
Save chiral/7785784 to your computer and use it in GitHub Desktop.
Adhoc mirror server in Node.js
var httpProxy = require('http-proxy');
var qs = require('querystring');
var url= require('url');
var redis = require('redis');
var cheerio = require('cheerio');
var ua= require('./ua');
var rc = redis.createClient();
var port=8081;
var default_ua = ua.pc;
function sdk_snippet(sel,html) {
console.log(sel);
console.log(html);
var s='<script src="http://codeorigin.jquery.com/jquery-1.10.2.min.js"></script>';
sel=sel.replace(/\"/g,"\\\"");
html=html.replace(/\"/g,"\\\"");
s+= '<script>$(function(){$("'+sel+'").html("'+html+'");});</script>';
return s;
}
function modify(req, res, rv) {
for (var k in req.headers) {
if (k.match(/^x-forwarded/)) {
delete req.headers[k];
}
}
delete req.headers.cookie;
delete req.headers.referer;
delete req.headers['user-agent'];
delete req.headers['accept-encoding'];
if (rv.ua) {
req.headers['user-agent'] = ua[rv.ua] || default_ua;
}
req.url = url.parse(req.url).path;
url_base = url.parse(rv.url);
if (req.url == url_base.path) {
req.headers.host = url_base.host;
if (rv.sel && rv.html) {
modify_res(res,sdk_snippet(rv.sel,rv.html));
}
}
}
function modify_res(res,snippet) {
var _write = res.write;
var _end = res.end;
var bufs = [];
res.write = function(d) {
bufs.push(d);
}
res.end = function() {
var buf = Buffer.concat(bufs).toString();
var $ = cheerio.load(buf);
$('head').append(snippet);
_write.call(res,$.html());
_end.call(res);
}
}
function do_proxy(key,proxy,req,res,id) {
rc.hgetall(key, function(err, redis_val){
if (err) {
console.log(err);
res.end();
} else {
var u = url.parse(redis_val.url);
modify(req, res, redis_val);
proxy.proxyRequest(req, res, {
host: u.host, port: u.port || 80
});
}
});
}
function decodeB64(a) {
return new Buffer(a,'base64').toString();
}
function record_url(req, res) {
var q = qs.parse(url.parse(req.url).query);
if (q.url && q.ua) {
var u = decodeB64(q.url);
var sel = q.sel?decodeB64(q.sel):'';
var html = q.html?decodeB64(q.html):'';
console.log([u,sel,html]);
rc.incr('proxy',function(err,id){
rc.hmset('proxy_'+id,{url:u,ua:q.ua,sel:sel,html:html});
res.setHeader('location','http://proxy_'+id+'.adfive.net:'+port+url.parse(u).pathname);
res.statusCode = 302;
res.end();
});
} else {
res.end();
}
}
httpProxy.createServer(function (req, res, proxy) {
var key = req.headers.host.split('.')[0];
if (key == 'proxy') {
record_url(req,res);
} else {
do_proxy(key,proxy,req,res);
}
}).listen(port, function(){
console.log("proxy start.");
});
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>アドホックミラーサーバ</title>
<script src="http://codeorigin.jquery.com/jquery-1.10.2.min.js"></script>
</head>
<body>
<h3>アドホックミラーサーバのテスト</h3>
<p>
広告SDKのプレビュー機能として作りましたが、
<font color="red">任意のサイトの「改変後の姿」を見れ</font>ます。<br>
</p>
<hr>
<div id="form">
<label>URL</label>
<input type="text" name="url" value="" />
<br>
<label>UserAgent</label>
<select name="ua">
<option value="pc_chrome">PC</option>
<option value="android4">Android</option>
<option value="iphone_ios6">iPhone</option>
<option value="ipad_ios6">iPad</option>
</select>
<br>
<br>
<label>差し替えたい箇所のセレクタ</label>
<input type="text" name="sel" value="" />
<br>
<label>差し替えるHTML</label>
<input type="text" name="html" value="" />
<br>
<br>
<input type="submit" value="Go" onClick="go()"/>
</div>
</body>
<script>
function go() {
var url=$("input[name=url]").val();
var ua=$("select[name=ua]").val();
var sel=$("input[name=sel]").val();
var html=$("input[name=html]").val();
var t="http://proxy.adfive.net:8081/?url="+btoa(url);
if (ua) t+="&ua="+ua;
if (sel) t+="&sel="+btoa(sel);
if (html) t+="&html="+btoa(html);
window.location=t;
}
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment