Skip to content

Instantly share code, notes, and snippets.

@yuest
Created November 24, 2011 05:05
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 yuest/1390663 to your computer and use it in GitHub Desktop.
Save yuest/1390663 to your computer and use it in GitHub Desktop.
A simple online debug tool for frontend developer, like fiddler2 on Windows.
/*
* tamper.js -
*
* author: yuest
* description:
*
*/
var http = require('http'),
fs = require('fs'),
path = require('path'),
crypto = require('crypto'),
config = {
"srcPath": "./src/"
};
config.srcPath = path.resolve( path.join( __dirname, config.srcPath ));
function fileHash(s) {
return crypto.createHash('sha1').update(s).digest('hex').substring(0, 10);
}
function Proxy() {
if ( this.constructor != Proxy ) {
return new Proxy();
}
var self = this;
var _patterns = [];
http.createServer(function (req, resp) {
var proxy = http.createClient(80, req.headers['host']);
proxy.on('error', function (e) {
console.error(e);
});
proxy.on('dajiangyou', function () {
console.log( 'dajiangyou: ' + req.url);
proxyReq = proxy.request(req.method, req.url, req.headers);
req.on('data', function (chunk) {
proxyReq.write(chunk, 'utf8');
});
req.on('end', function () {
proxyReq.end();
});
proxyReq.on('response', function (proxyResp) {
resp.writeHead(proxyResp.statusCode, proxyResp.headers);
proxyResp.on('error', function (e) {
console.error(e);
});
proxyResp.on('data', function (chunk) {
resp.write(chunk);
});
proxyResp.on('end', function () {
resp.end();
});
});
});
var filePath = self.getFilePath(req.url);
if (!filePath) {
return proxy.emit('dajiangyou');
}
fs.readFile( filePath, function (err, content) {
if (err) {
return proxy.emit('dajiangyou');
}
//终于确认需要代理,不是打酱油的了。
console.log( 'tampered: ' + filePath );
resp.writeHead(200, {
'Content-Type': self.contentTypeMap[ path.extname( filePath )]
});
resp.write(content, 'utf8');
resp.end();
return;
});
}).listen(8080);
this.contentTypeMap = {
'.js': 'text/javascript; charset=utf-8',
'.css': 'text/css; charset=utf-8',
'.html': 'text/html; charset=utf-8',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.gif': 'image/gif'
};
this.addPattern = function (pattern) {
_patterns.push( pattern );
};
this.addPatterns = function (patterns) {
_patterns = _patterns.concat( patterns );
};
this.getFilePath = function (url) {
var params,
matched = false,
extname,
filePath,
originalFilePath,
reqPath = url.replace(/(https?:\/\/[^\/]+)/g, '').replace(/\?.+/, function (m) {
params = m;
return '';
});
for (var i = -1, pattern; pattern = _patterns[++i]; ) {
if (typeof pattern == 'string') {
if (/^\/sandbox/.test( pattern )) {
if (path.join( '/sandbox', reqPath ) == pattern) {
reqPath = path.join( '/sandbox', reqPath );
matched = true;
break;
}
} else if (reqPath == pattern) {
matched = true;
break;
}
} else if (pattern instanceof RegExp) {
if (String( pattern ) == '/^\\/sandbox\\/.*/') {
reqPath = path.join( '/sandbox', reqPath );
matched = true;
break;
} else if ( pattern.test( reqPath )) {
matched = true;
break;
}
}
}
if (!matched ) {
return false;
}
filePath = path.join( config.srcPath, reqPath );
if (filePath[filePath.length-1] == '/') {
filePath = path.join( filePath, 'index.html' );
}
extname = path.extname( filePath );
if (!self.contentTypeMap.hasOwnProperty( extname )) {
return false;
}
originalFilePath= filePath;
if (params) {
filePath = filePath.substring(0, filePath.lastIndexOf( extname )) +
'__' + fileHash( params ) + extname;
console.log('try to tamper: '+ filePath);
}
if (!path.existsSync( filePath )) {
if (originalFilePath && path.existsSync( originalFilePath )) {
return originalFilePath;
} else {
return false;
}
}
return filePath;
};
}
function startProxy(){
var proxy = Proxy();
var argv = [].slice.apply(process.argv);
var patterns = [];
if (argv.length > 2) {
argv.splice(0,2);
}
var prefix = null,
allFlag = 0,
dirMap = {'-j':'/js', '-c':'/skin', '-s':'/sandbox', '-z':'/zone', '-i':'/skin/imgs'},
flagMap = {'-J':1, '-C':2, '-S':4, '-Z':8, '-I':16};
for (var i = -1, arg; arg = argv[++i]; ) {
if (arg in flagMap) {
patterns.push( new RegExp( '^\\' + dirMap[arg.toLowerCase()]
+ '\\/.*' ));
prefix = null;
} else if (arg in dirMap) {
prefix = dirMap[arg];
} else if (prefix !== null) {
patterns.push( path.join( prefix, arg ));
}
}
proxy.addPatterns(patterns);
}
startProxy();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment