用 nodejs 做反向代理服务器

时下不少场景,都是申请一个 VPS 主机来托管运行 Web 项目的,小弟我也不例外——购买了一个小型的 CentOS VPS 使用着。在使用的过程中,面临一个问题,就是同一类型的服务端环境还好——但如果是一个 PHP、一个 ASP、 一个 JSP 的三种类型的服务端项目并存着,该怎么分配唯一的 80 端口呢?因为商业 WWW 网站的话,往往只能占用 80  端口,——当然,如果只是做服务的话,如接口服务之类的,使用了其他端口就不会与 80 端口冲突。因此,许多开发者都会面临到 80 端口这个问题,并且实际情况会受到成本的限制。如果为一个项目就单独买一个 VPS 的话,着实不太经济、不太合算,管理起来也不方便。这样的话,我们就应该好好考虑一下,怎么在提供一个 80 端口的情况下,分发到多种服务端那里去,最终让不同的主机执行各自的 Web 项目。

亲,那么这项需求是可以实现的吗?是的,而且并不是什么“神奇的技术”,也不是什么复杂的技术。不知你是否有了解,网络服务中的“反向代理(Reverse Proxy)”,其中的一个功能就是可以完成端口的分发的。我们不妨以域名为“路由分发”:凡是 AA.com 域名请求的,分发到 PHP 82 端口执行;凡是 BB.com 域名请求的,分发到 ASP 83 端口执行;…… 如此类推。当然这里的端口只说说明用而已,您可以任意配置,反正就是从 80 端口接收回来的请求,先作一次处理,进而分发。反向代理,通俗地讲,就是左手转右手而已。

每当提起反向代理器,人们通常一想到的就是 Nginx,但是今天我们暂时忽略大名鼎鼎的 Nginx,采用同样也是使用单线程、事件循环的服务端小弟——Node 来达成。首先 Node 采用 JS 作服务端编程,而不是 Nginx 写配置或 Lua,比较符合我的味口,其次自己对 Node 也比较熟悉,配置各方面什么的更为顺手。

完成该项功能的是 node-http-proxy 包。下载、安装请键入:

npm install http-proxy

安装完毕后,新建一个 proxy.js 文件,输入:

var http = require('http'), httpProxy = require('http-proxy');

// 新建一个代理 Proxy Server 对象
var proxy = httpProxy.createProxyServer({});

// 捕获异常
proxy.on('error', function (err, req, res) {
  res.writeHead(500, {
    'Content-Type': 'text/plain'
  });
  res.end('Something went wrong. And we are reporting a custom error message.');
});

// 另外新建一个 HTTP 80 端口的服务器,也就是常规 Node 创建 HTTP 服务器的方法。
// 在每次请求中,调用 proxy.web(req, res config) 方法进行请求分发
var server = require('http').createServer(function(req, res) {
  // 在这里可以自定义你的路由分发
  var host = req.headers.host, ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
  console.log("client ip:" + ip + ", host:" + host);
  
  switch(host){
    case 'aaaa.com':
    case 'bbs.aaaa.com':
        proxy.web(req, res, { target: 'http://xyd.bbbbb.com:82' });
    break;
    case 'vps.cccc.com':
        proxy.web(req, res, { target: 'http://xyd.bbbbb.com:8080' });
    break;
    case 'dddd.com':
    case 'www.dddd.com':
        proxy.web(req, res, { target: 'http://localhost:81' });
    break;
    case 'eeeeee.com.cn':
    case 'www.eeee.com.cn':
        proxy.web(req, res, { target: 'http://eeeee.com.cn:8082' });
    break;
    default:
        res.writeHead(200, {
            'Content-Type': 'text/plain'
        });
        res.end('Welcome to my server!');
  }
});

console.log("listening on port 80")
server.listen(80);

除此之外,还可以利用 node-http-proxy 做负载均衡、Websocket (使用 proxy.ws() 语法)等相关的工作。

若说使用代理服务器的代价,可能就是会比不用消耗多的资源,消耗多的 CPU 运算罢了。

使用问题:不能指定文件夹 proxy.web(req, res, { target: 'http://housecn.com.cn:81/foo/' });

可以在一个主机上配置多个网站了:2015--5-28:

switch(host){  
        case '5222222.com':  
        case 'www.5222222.com':
			if(req.url.indexOf('/grand') != -1){
				proxy.web(req, res, { target: 'http://127.0.0.1:8081' });  
			}else{
				res.writeHead(302, {
				//  'Location': 'http://new.5222222.com:8080/grand/'
				  'Location': 'http://5222222.com/grand/'
				
				});
				res.end();
			}
          break;
  ....
}

资源:

附带一个 静态服务器

const http = require('http');  //引入node http模块
const fs = require('fs');    //引入node 文件读写fs模块
const path = require('path');   //引入 node path模块
const url = require('url');     //引入  url  模块
const resMime = require('./resMime.js'); //引入自定义模块,模块主要处理响应头

const config = {
    port: 8888,
    webRoot: require('os').type() == 'Darwin' ? '/Users/xinzhang/dev/project/aj-ts/' : 'C:\\project\\aj-ts'
};
const server = http.createServer((req, res) => {    // http.createServer()创建服务器
    let pathName = url.parse(req.url).pathname;     // 获取req.url,并且转换请求的路径
    // console.log(url.parse('index.html/12323123'));  会得到 index.html
    // console.log(pathName); // 控制台打印看能不能得到请求路径

    if (pathName == '/')   // 如果请求为空或“/”,则把请求路径改为index.html
        pathName = '/index.html';

    if (pathName == '/favicon.ico')  // 如果请求为“/favicon.ico”图标,则直接结束不处理
        res.end();
    else {
        // 这里正式写处理逻辑
        // console.log('开始读取文件');
        let extName = path.extname(pathName);//拿到扩展名(比如说:'index.html' => '.html')
        
        // 下面用到 fs 去读取客户端请求的文件,path.join拼接成绝对路径
        fs.readFile(path.join(config.webRoot || __dirname, pathName), function (err, data) {   // 绝对路径,path.jion(__dirname,pathName)
            if (err) {
                // 没有找到的话,就走ERR,转去加载404页面
                console.log(err);
                res.writeHead(404, { "Content-Type": "text/html;chartset='utf8'" })
                res.write("Not found"); // 把文件写回客户端
                res.end();   // 结束
                // fs.readFile(path.join(config.webRoot || __dirname, `404.html`), (err, data) => {
                //     // res.writeHead()向客户端返回响应头,状态码404,因为返回的是自己写的404页面,所以响应头应该为"Content-Type":"text/html;chartset='utf8'" 
                //     res.writeHead(404, { "Content-Type": "text/html;chartset='utf8'" })
                //     res.write(data); // 把文件写回客户端
                //     res.end();   // 结束
                // })
            } else {
                // 这里fs找到了请求资源
                // console.log(data) // 打印看看资源的内容
                var mime = resMime.getMime(fs, extName);  // 调用外部模块resMime,这个模块我是用来,请求的文件后缀名转换成mime标准的响应头Content-Type类型(比如说:'.css'=>'text/css','.js'=>'text/javascript')
                res.writeHead(200, { "Content-Type": `${mime};chartset='utf8'` });
                res.write(data); // 把文件写回客户端
                res.end();   // 结束
            }
        });

    }

});

server.listen(config.port);    // 让服务器跑在8887端口
console.log('Server ready');

resMime.js

const Mimes = {
    ".323": "text/h323",
    ".3gp": "video/3gpp",
    ".aab": "application/x-authoware-bin",
    ".aam": "application/x-authoware-map",
    ".aas": "application/x-authoware-seg",
    ".acx": "application/internet-property-stream",
    ".ai": "application/postscript",
    ".aif": "audio/x-aiff",
    ".aifc": "audio/x-aiff",
    ".aiff": "audio/x-aiff",
    ".als": "audio/X-Alpha5",
    ".amc": "application/x-mpeg",
    ".ani": "application/octet-stream",
    ".apk": "application/vnd.android.package-archive",
    ".asc": "text/plain",
    ".asd": "application/astound",
    ".asf": "video/x-ms-asf",
    ".asn": "application/astound",
    ".asp": "application/x-asap",
    ".asr": "video/x-ms-asf",
    ".asx": "video/x-ms-asf",
    ".au": "audio/basic",
    ".avb": "application/octet-stream",
    ".avi": "video/x-msvideo",
    ".awb": "audio/amr-wb",
    ".axs": "application/olescript",
    ".bas": "text/plain",
    ".bcpio": "application/x-bcpio",
    ".bin ": "application/octet-stream",
    ".bld": "application/bld",
    ".bld2": "application/bld2",
    ".bmp": "image/bmp",
    ".bpk": "application/octet-stream",
    ".bz2": "application/x-bzip2",
    ".c": "text/plain",
    ".cal": "image/x-cals",
    ".cat": "application/vnd.ms-pkiseccat",
    ".ccn": "application/x-cnc",
    ".cco": "application/x-cocoa",
    ".cdf": "application/x-cdf",
    ".cer": "application/x-x509-ca-cert",
    ".cgi": "magnus-internal/cgi",
    ".chat": "application/x-chat",
    ".class": "application/octet-stream",
    ".clp": "application/x-msclip",
    ".cmx": "image/x-cmx",
    ".co": "application/x-cult3d-object",
    ".cod": "image/cis-cod",
    ".conf": "text/plain",
    ".cpio": "application/x-cpio",
    ".cpp": "text/plain",
    ".cpt": "application/mac-compactpro",
    ".crd": "application/x-mscardfile",
    ".crl": "application/pkix-crl",
    ".crt": "application/x-x509-ca-cert",
    ".csh": "application/x-csh",
    ".csm": "chemical/x-csml",
    ".csml": "chemical/x-csml",
    ".css": "text/css",
    ".cur": "application/octet-stream",
    ".dcm": "x-lml/x-evm",
    ".dcr": "application/x-director",
    ".dcx": "image/x-dcx",
    ".der": "application/x-x509-ca-cert",
    ".dhtml": "text/html",
    ".dir": "application/x-director",
    ".dll": "application/x-msdownload",
    ".dmg": "application/octet-stream",
    ".dms": "application/octet-stream",
    ".doc": "application/msword",
    ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    ".dot": "application/msword",
    ".dvi": "application/x-dvi",
    ".dwf": "drawing/x-dwf",
    ".dwg": "application/x-autocad",
    ".dxf": "application/x-autocad",
    ".dxr": "application/x-director",
    ".ebk": "application/x-expandedbook",
    ".emb": "chemical/x-embl-dl-nucleotide",
    ".embl": "chemical/x-embl-dl-nucleotide",
    ".eps": "application/postscript",
    ".epub": "application/epub+zip",
    ".eri": "image/x-eri",
    ".es": "audio/echospeech",
    ".esl": "audio/echospeech",
    ".etc": "application/x-earthtime",
    ".etx": "text/x-setext",
    ".evm": "x-lml/x-evm",
    ".evy": "application/envoy",
    ".exe": "application/octet-stream",
    ".fh4": "image/x-freehand",
    ".fh5": "image/x-freehand",
    ".fhc": "image/x-freehand",
    ".fif": "application/fractals",
    ".flr": "x-world/x-vrml",
    ".flv": "flv-application/octet-stream",
    ".fm": "application/x-maker",
    ".fpx": "image/x-fpx",
    ".fvi": "video/isivideo",
    ".gau": "chemical/x-gaussian-input",
    ".gca": "application/x-gca-compressed",
    ".gdb": "x-lml/x-gdb",
    ".gif": "image/gif",
    ".gps": "application/x-gps",
    ".gtar": "application/x-gtar",
    ".gz": "application/x-gzip",
    ".h": "text/plain",
    ".hdf": "application/x-hdf",
    ".hdm": "text/x-hdml",
    ".hdml": "text/x-hdml",
    ".hlp": "application/winhlp",
    ".hqx": "application/mac-binhex40",
    ".hta": "application/hta",
    ".htc": "text/x-component",
    ".htm": "text/html",
    ".html": "text/html",
    ".hts": "text/html",
    ".htt": "text/webviewhtml",
    ".ice": "x-conference/x-cooltalk",
    ".ico": "image/x-icon",
    ".ief": "image/ief",
    ".ifm": "image/gif",
    ".ifs": "image/ifs",
    ".iii": "application/x-iphone",
    ".imy": "audio/melody",
    ".ins": "application/x-internet-signup",
    ".ips": "application/x-ipscript",
    ".ipx": "application/x-ipix",
    ".isp": "application/x-internet-signup",
    ".it": "audio/x-mod",
    ".itz": "audio/x-mod",
    ".ivr": "i-world/i-vrml",
    ".j2k": "image/j2k",
    ".jad": "text/vnd.sun.j2me.app-descriptor",
    ".jam": "application/x-jam",
    ".jar": "application/java-archive",
    ".java": "text/plain",
    ".jfif": "image/pipeg",
    ".jnlp": "application/x-java-jnlp-file",
    ".jpe": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".jpg": "image/jpeg",
    ".jpz": "image/jpeg",
    ".js": "application/x-javascript",
    ".jwc": "application/jwc",
    ".kjx": "application/x-kjx",
    ".lak": "x-lml/x-lak",
    ".latex": "application/x-latex",
    ".lcc": "application/fastman",
    ".lcl": "application/x-digitalloca",
    ".lcr": "application/x-digitalloca",
    ".lgh": "application/lgh",
    ".lha": "application/octet-stream",
    ".lml": "x-lml/x-lml",
    ".lmlpack": "x-lml/x-lmlpack",
    ".log": "text/plain",
    ".lsf": "video/x-la-asf",
    ".lsx": "video/x-la-asf",
    ".lzh": "application/octet-stream",
    ".m13": "application/x-msmediaview",
    ".m14": "application/x-msmediaview",
    ".m15": "audio/x-mod",
    ".m3u": "audio/x-mpegurl",
    ".m3url": "audio/x-mpegurl",
    ".m4a": "audio/mp4a-latm",
    ".m4b": "audio/mp4a-latm",
    ".m4p": "audio/mp4a-latm",
    ".m4u": "video/vnd.mpegurl",
    ".m4v": "video/x-m4v",
    ".ma1": "audio/ma1",
    ".ma2": "audio/ma2",
    ".ma3": "audio/ma3",
    ".ma5": "audio/ma5",
    ".man": "application/x-troff-man",
    ".map": "magnus-internal/imagemap",
    ".mbd": "application/mbedlet",
    ".mct": "application/x-mascot",
    ".mdb": "application/x-msaccess",
    ".mdz": "audio/x-mod",
    ".me": "application/x-troff-me",
    ".mel": "text/x-vmel",
    ".mht": "message/rfc822",
    ".mhtml": "message/rfc822",
    ".mi": "application/x-mif",
    ".mid": "audio/mid",
    ".midi": "audio/midi",
    ".mif": "application/x-mif",
    ".mil": "image/x-cals",
    ".mio": "audio/x-mio",
    ".mmf": "application/x-skt-lbs",
    ".mng": "video/x-mng",
    ".mny": "application/x-msmoney",
    ".moc": "application/x-mocha",
    ".mocha": "application/x-mocha",
    ".mod": "audio/x-mod",
    ".mof": "application/x-yumekara",
    ".mol": "chemical/x-mdl-molfile",
    ".mop": "chemical/x-mopac-input",
    ".mov": "video/quicktime",
    ".movie": "video/x-sgi-movie",
    ".mp2": "video/mpeg",
    ".mp3": "audio/mpeg",
    ".mp4": "video/mp4",
    ".mpa": "video/mpeg",
    ".mpc": "application/vnd.mpohun.certificate",
    ".mpe": "video/mpeg",
    ".mpeg": "video/mpeg",
    ".mpg": "video/mpeg",
    ".mpg4": "video/mp4",
    ".mpga": "audio/mpeg",
    ".mpn": "application/vnd.mophun.application",
    ".mpp": "application/vnd.ms-project",
    ".mps": "application/x-mapserver",
    ".mpv2": "video/mpeg",
    ".mrl": "text/x-mrml",
    ".mrm": "application/x-mrm",
    ".ms": "application/x-troff-ms",
    ".msg": "application/vnd.ms-outlook",
    ".mts": "application/metastream",
    ".mtx": "application/metastream",
    ".mtz": "application/metastream",
    ".mvb": "application/x-msmediaview",
    ".mzv": "application/metastream",
    ".nar": "application/zip",
    ".nbmp": "image/nbmp",
    ".nc": "application/x-netcdf",
    ".ndb": "x-lml/x-ndb",
    ".ndwn": "application/ndwn",
    ".nif": "application/x-nif",
    ".nmz": "application/x-scream",
    ".nokia-op-logo": "image/vnd.nok-oplogo-color",
    ".npx": "application/x-netfpx",
    ".nsnd": "audio/nsnd",
    ".nva": "application/x-neva1",
    ".nws": "message/rfc822",
    ".oda": "application/oda",
    ".ogg": "audio/ogg",
    ".oom": "application/x-AtlasMate-Plugin",
    ".p10": "application/pkcs10",
    ".p12": "application/x-pkcs12",
    ".p7b": "application/x-pkcs7-certificates",
    ".p7c": "application/x-pkcs7-mime",
    ".p7m": "application/x-pkcs7-mime",
    ".p7r": "application/x-pkcs7-certreqresp",
    ".p7s": "application/x-pkcs7-signature",
    ".pac": "audio/x-pac",
    ".pae": "audio/x-epac",
    ".pan": "application/x-pan",
    ".pbm": "image/x-portable-bitmap",
    ".pcx": "image/x-pcx",
    ".pda": "image/x-pda",
    ".pdb": "chemical/x-pdb",
    ".pdf": "application/pdf",
    ".pfr": "application/font-tdpfr",
    ".pfx": "application/x-pkcs12",
    ".pgm": "image/x-portable-graymap",
    ".pict": "image/x-pict",
    ".pko": "application/ynd.ms-pkipko",
    ".pm": "application/x-perl",
    ".pma": "application/x-perfmon",
    ".pmc": "application/x-perfmon",
    ".pmd": "application/x-pmd",
    ".pml": "application/x-perfmon",
    ".pmr": "application/x-perfmon",
    ".pmw": "application/x-perfmon",
    ".png": "image/png",
    ".pnm": "image/x-portable-anymap",
    ".pnz": "image/png",
    ".pot,": "application/vnd.ms-powerpoint",
    ".ppm": "image/x-portable-pixmap",
    ".pps": "application/vnd.ms-powerpoint",
    ".ppt": "application/vnd.ms-powerpoint",
    ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
    ".pqf": "application/x-cprplayer",
    ".pqi": "application/cprplayer",
    ".prc": "application/x-prc",
    ".prf": "application/pics-rules",
    ".prop": "text/plain",
    ".proxy": "application/x-ns-proxy-autoconfig",
    ".ps": "application/postscript",
    ".ptlk": "application/listenup",
    ".pub": "application/x-mspublisher",
    ".pvx": "video/x-pv-pvx",
    ".qcp": "audio/vnd.qcelp",
    ".qt": "video/quicktime",
    ".qti": "image/x-quicktime",
    ".qtif": "image/x-quicktime",
    ".r3t": "text/vnd.rn-realtext3d",
    ".ra": "audio/x-pn-realaudio",
    ".ram": "audio/x-pn-realaudio",
    ".rar": "application/octet-stream",
    ".ras": "image/x-cmu-raster",
    ".rc": "text/plain",
    ".rdf": "application/rdf+xml",
    ".rf": "image/vnd.rn-realflash",
    ".rgb": "image/x-rgb",
    ".rlf": "application/x-richlink",
    ".rm": "audio/x-pn-realaudio",
    ".rmf": "audio/x-rmf",
    ".rmi": "audio/mid",
    ".rmm": "audio/x-pn-realaudio",
    ".rmvb": "audio/x-pn-realaudio",
    ".rnx": "application/vnd.rn-realplayer",
    ".roff": "application/x-troff",
    ".rp": "image/vnd.rn-realpix",
    ".rpm": "audio/x-pn-realaudio-plugin",
    ".rt": "text/vnd.rn-realtext",
    ".rte": "x-lml/x-gps",
    ".rtf": "application/rtf",
    ".rtg": "application/metastream",
    ".rtx": "text/richtext",
    ".rv": "video/vnd.rn-realvideo",
    ".rwc": "application/x-rogerwilco",
    ".s3m": "audio/x-mod",
    ".s3z": "audio/x-mod",
    ".sca": "application/x-supercard",
    ".scd": "application/x-msschedule",
    ".sct": "text/scriptlet",
    ".sdf": "application/e-score",
    ".sea": "application/x-stuffit",
    ".setpay": "application/set-payment-initiation",
    ".setreg": "application/set-registration-initiation",
    ".sgm": "text/x-sgml",
    ".sgml": "text/x-sgml",
    ".sh": "application/x-sh",
    ".shar": "application/x-shar",
    ".shtml": "magnus-internal/parsed-html",
    ".shw": "application/presentations",
    ".si6": "image/si6",
    ".si7": "image/vnd.stiwap.sis",
    ".si9": "image/vnd.lgtwap.sis",
    ".sis": "application/vnd.symbian.install",
    ".sit": "application/x-stuffit",
    ".skd": "application/x-Koan",
    ".skm": "application/x-Koan",
    ".skp": "application/x-Koan",
    ".skt": "application/x-Koan",
    ".slc": "application/x-salsa",
    ".smd": "audio/x-smd",
    ".smi": "application/smil",
    ".smil": "application/smil",
    ".smp": "application/studiom",
    ".smz": "audio/x-smd",
    ".snd": "audio/basic",
    ".spc": "application/x-pkcs7-certificates",
    ".spl": "application/futuresplash",
    ".spr": "application/x-sprite",
    ".sprite": "application/x-sprite",
    ".sdp": "application/sdp",
    ".spt": "application/x-spt",
    ".src": "application/x-wais-source",
    ".sst": "application/vnd.ms-pkicertstore",
    ".stk": "application/hyperstudio",
    ".stl": "application/vnd.ms-pkistl",
    ".stm": "text/html",
    ".svg": "image/svg+xml",
    ".sv4cpio": "application/x-sv4cpio",
    ".sv4crc": "application/x-sv4crc",
    ".svf": "image/vnd",
    ".svg": "image/svg+xml",
    ".svh": "image/svh",
    ".svr": "x-world/x-svr",
    ".swf": "application/x-shockwave-flash",
    ".swfl": "application/x-shockwave-flash",
    ".t": "application/x-troff",
    ".tad": "application/octet-stream",
    ".talk": "text/x-speech",
    ".tar": "application/x-tar",
    ".taz": "application/x-tar",
    ".tbp": "application/x-timbuktu",
    ".tbt": "application/x-timbuktu",
    ".tcl": "application/x-tcl",
    ".tex": "application/x-tex",
    ".texi": "application/x-texinfo",
    ".texinfo": "application/x-texinfo",
    ".tgz": "application/x-compressed",
    ".thm": "application/vnd.eri.thm",
    ".tif": "image/tiff",
    ".tiff": "image/tiff",
    ".tki": "application/x-tkined",
    ".tkined": "application/x-tkined",
    ".toc": "application/toc",
    ".toy": "image/toy",
    ".tr": "application/x-troff",
    ".trk": "x-lml/x-gps",
    ".trm": "application/x-msterminal",
    ".tsi": "audio/tsplayer",
    ".tsp": "application/dsptype",
    ".tsv": "text/tab-separated-values",
    ".ttf": "application/octet-stream",
    ".ttz": "application/t-time",
    ".txt": "text/plain",
    ".uls": "text/iuls",
    ".ult": "audio/x-mod",
    ".ustar": "application/x-ustar",
    ".uu": "application/x-uuencode",
    ".uue": "application/x-uuencode",
    ".vcd": "application/x-cdlink",
    ".vcf": "text/x-vcard",
    ".vdo": "video/vdo",
    ".vib": "audio/vib",
    ".viv": "video/vivo",
    ".vivo": "video/vivo",
    ".vmd": "application/vocaltec-media-desc",
    ".vmf": "application/vocaltec-media-file",
    ".vmi": "application/x-dreamcast-vms-info",
    ".vms": "application/x-dreamcast-vms",
    ".vox": "audio/voxware",
    ".vqe": "audio/x-twinvq-plugin",
    ".vqf": "audio/x-twinvq",
    ".vql": "audio/x-twinvq",
    ".vre": "x-world/x-vream",
    ".vrml": "x-world/x-vrml",
    ".vrt": "x-world/x-vrt",
    ".vrw": "x-world/x-vream",
    ".vts": "workbook/formulaone",
    ".wav": "audio/x-wav",
    ".wax": "audio/x-ms-wax",
    ".wbmp": "image/vnd.wap.wbmp",
    ".wcm": "application/vnd.ms-works",
    ".wdb": "application/vnd.ms-works",
    ".web": "application/vnd.xara",
    ".wi": "image/wavelet",
    ".wis": "application/x-InstallShield",
    ".wks": "application/vnd.ms-works",
    ".wm": "video/x-ms-wm",
    ".wma": "audio/x-ms-wma",
    ".wmd": "application/x-ms-wmd",
    ".wmf": "application/x-msmetafile",
    ".wml": "text/vnd.wap.wml",
    ".wmlc": "application/vnd.wap.wmlc",
    ".wmls": "text/vnd.wap.wmlscript",
    ".wmlsc": "application/vnd.wap.wmlscriptc",
    ".wmlscript": "text/vnd.wap.wmlscript",
    ".wmv": "audio/x-ms-wmv",
    ".wmx": "video/x-ms-wmx",
    ".wmz": "application/x-ms-wmz",
    ".wpng": "image/x-up-wpng",
    ".wps": "application/vnd.ms-works",
    ".wpt": "x-lml/x-gps",
    ".wri": "application/x-mswrite",
    ".wrl": "x-world/x-vrml",
    ".wrz": "x-world/x-vrml",
    ".ws": "text/vnd.wap.wmlscript",
    ".wsc": "application/vnd.wap.wmlscriptc",
    ".wv": "video/wavelet",
    ".wvx": "video/x-ms-wvx",
    ".wxl": "application/x-wxl",
    ".x-gzip": "application/x-gzip",
    ".xaf": "x-world/x-vrml",
    ".xar": "application/vnd.xara",
    ".xbm": "image/x-xbitmap",
    ".xdm": "application/x-xdma",
    ".xdma": "application/x-xdma",
    ".xdw": "application/vnd.fujixerox.docuworks",
    ".xht": "application/xhtml+xml",
    ".xhtm": "application/xhtml+xml",
    ".xhtml": "application/xhtml+xml",
    ".xla": "application/vnd.ms-excel",
    ".xlc": "application/vnd.ms-excel",
    ".xll": "application/x-excel",
    ".xlm": "application/vnd.ms-excel",
    ".xls": "application/vnd.ms-excel",
    ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    ".xlt": "application/vnd.ms-excel",
    ".xlw": "application/vnd.ms-excel",
    ".xm": "audio/x-mod",
    ".xml": "text/plain",
    ".xml": "application/xml",
    ".xmz": "audio/x-mod",
    ".xof": "x-world/x-vrml",
    ".xpi": "application/x-xpinstall",
    ".xpm": "image/x-xpixmap",
    ".xsit": "text/xml",
    ".xsl": "text/xml",
    ".xul": "text/xul",
    ".xwd": "image/x-xwindowdump",
    ".xyz": "chemical/x-pdb",
    ".yz1": "application/x-yz1",
    ".z": "application/x-compress",
    ".zac": "application/x-zaurus-zac",
    ".zip": "application/zip",
    ".json": "application/json"
};

exports.getMime = (fs, extname) => Mimes[extname] || 'text/html';

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sp42a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值