Created
November 24, 2011 05:05
-
-
Save yuest/1390663 to your computer and use it in GitHub Desktop.
A simple online debug tool for frontend developer, like fiddler2 on Windows.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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