nodejs下载器,通过chrome代理下载http资源

var config={
    //不想访问的东西,节约流量
    "404":[
        "http://qidian.qpic.cn/qdbimg"
    ],
    //奇数为需要下载的,偶数为不需要下载的
    needLoad:[
        //匹配需要下载的
        [
            "/*.js",
            "/*.css",
            "/*.png"
        ],
        //匹配不需要下载的
        [
            "/a.js"
        ]
    ],
    //修改文件保存的地方,默认按照url来的
    saveFiles:[
        //防止太深文件夹
        ["(//*/*/*/*/*/)**/","$1"],
        //过滤无效文件夹字符
        [/(/w*)?+(w*/)/gi,"$1$2"]
    ],
    //代理的端口号
    port:100
}

function regDir(str){
    var reg=str
    if(typeof reg=="string"){
        reg=reg.replace(/[[]\^:.?+]/g,function(m){
            return "\"+m;
        })
        reg=reg.replace(/**|*/g,function(m){
            if(m=="**"){
                return "[\w\W]*";
            }else{
                return "[^\/]*";
            }

        })
        reg=new RegExp(reg,"gi")
    }
    return reg
}
String.prototype.Test=function(regStr){
    var reg=regDir(regStr)
    return reg.test(this)
}
String.prototype.Replace=function(regStr,fn){
    var reg=regDir(regStr)
    return this.replace(reg,fn);
}
var fs=require("fs")
function mkdir(filepath){
    var path=require("path")
    if(!fs.existsSync(path.dirname(filepath))){
        mkdir(path.dirname(filepath))
    }
    if(!fs.existsSync(filepath)){
        fs.mkdirSync(filepath)
    }
}


function eachHeader (obj, fn) {
    if (Array.isArray(obj.rawHeaders)) {
        // ideal scenario... >= node v0.11.x
        // every even entry is a "key", every odd entry is a "value"
        var key = null;
        obj.rawHeaders.forEach(function (v) {
            if (key === null) {
                key = v;
            } else {
                fn(key, v);
                key = null;
            }
        });
    } else {
        // otherwise we can *only* proxy the header names as lowercase'd
        var headers = obj.headers;
        if (!headers) return;
        Object.keys(headers).forEach(function (key) {
            var value = headers[key];
            if (Array.isArray(value)) {
                // set-cookie
                value.forEach(function (val) {
                    fn(key, val);
                });
            } else {
                fn(key, value);
            }
        });
    }
}
var hopByHopHeaders = [
    'Connection',
    'Keep-Alive',
    'Proxy-Authenticate',
    'Proxy-Authorization',
    'TE',
    'Trailers',
    'Transfer-Encoding',
    'Upgrade'
];
// create a case-insensitive RegExp to match "hop by hop" headers
var isHopByHop = new RegExp('^(' + hopByHopHeaders.join('|') + ')$', 'i');
//伪造http
function parse (req, server) {

    var parsed = require("url").parse(req.url);
    var socket = req.socket;
    parsed.uri=parsed.href;
    parsed.gzip=true;
    // proxy the request HTTP method
    parsed.method = req.method;

    // setup outbound proxy request HTTP headers
    var headers = {};
    var hasXForwardedFor = false;
    parsed.headers = headers;
    eachHeader(req, function (key, value) {
        var keyLower = key.toLowerCase();
        if (!hasXForwardedFor && 'x-forwarded-for' === keyLower) {
            // append to existing "X-Forwarded-For" header
            // http://en.wikipedia.org/wiki/X-Forwarded-For
            hasXForwardedFor = true;
            value += ', ' + socket.remoteAddress;
        }
        if (isHopByHop.test(key)) {
        } else {
            var v = headers[key];
            if (Array.isArray(v)) {
                v.push(value);
            } else if (null != v) {
                headers[key] = [ v, value ];
            } else {
                headers[key] = value;
            }
        }
    });

    if (!hasXForwardedFor) {
        headers['X-Forwarded-For'] = socket.remoteAddress;
    }
    if (null == parsed.port) {
        // default the port number if not specified, for >= node v0.11.6...
        // https://github.com/joyent/node/issues/6199
        parsed.port = 80;
    }
    return parsed
}

function getPath(url){
    var filename=url.Replace("(**)?*","$1").Replace("http://(**/*)","$1")
    var dirname=filename.Replace("(**)/*","$1")
    mkdir("www/"+dirname)
    return "www/"+filename
}
var api={
    parse:parse,
    mkdir:mkdir,
    getPath:getPath
}
/************************************/
var http = require('http');
var fs=require("fs")
var request = require('request');


var server = http.createServer();
server.listen(config.port||100, function () {
    var port = server.address().port;
    console.log('HTTP(s) proxy server listening on port %d', port);
});

server.on('request', function (req, res) {

    var url=req.url
    var arr404=config["404"]
    var is404=false
    arr404.forEach(function(v,k){
        if(url.Test(v)){
            is404=true
        }
    })
    if(is404){
        res.end()
        return
    }
    var parsed=api.parse(req,this)
    //是否下载
    var isLoaded=false;

    //是否下载的列表
    var regArr=config.needLoad
    var back=false
    regArr.forEach(function(v,k){
        back=!back
        v.forEach(function(v2,k2){
            if(url.Test(v2)){
                isLoaded=back
            }
        })
    })
    //修改保存文件路径
    /*
     * 匹配规则
     * 修改后 */
    var saveFiles=config.saveFiles
//    isLoaded=false
    if(isLoaded){
        saveFiles.forEach(function(v,k){
            url=url.Replace(v[0],v[1])
        })
        console.log(url)
        var path=api.getPath(url)
        console.log(path)
        //下载
        var reque=request(parsed,function(err,resp,body){
            if(err){
                return
            }
            if(path.Test("/*.css")){
                res.writeHead(200,{
                    "content-type":"text/css"
                })
            }
            fs.createReadStream(path).pipe(res)
        })
        reque.pipe(fs.createWriteStream(path))
        reque.on("error",function(){
            console.error(url)
        })

    }else{
        //不下载
        var reque=request(parsed)
        reque.pipe(res)
        reque.on("error",function(){
            console.error(url)
        })

    }


})

  

原文地址:https://www.cnblogs.com/caoke/p/6047614.html