前言、没图不说话,先上图。

What's webhere?

有没有遇到这样的场景:写程序的时候,需要访问一个文件,这个文件 需要是放到一台web服务器上,但是你不是开发的web应用。

所以呢,你不得不去找一个web服务器,把你的文件上传上去,或者干脆直接创建一个web应用程序...

webhere就是来解决这个问题,在你想要当做web根目录的目录下,打开你亲爱的命令行,敲下webhere,回车,搞定。

然后就可以通过web浏览器访问目录下的文件了。

安装:$ npm install webhere -g

运行:$ webhere

一、 原理

原理比较简单,一句话来说,就是搭建一个web服务器。

1.用nodejs的http包创建一个web服务。

2.对访问路径路由到具体的文件路径。

3.根据文件是否存在写具体的响应码,根据文件的后缀写具体Content-type。

4.返回文件的内容,响应结束。

二、 实现

1.创建nodejs的pakage.json,添加应用的bin的信息和其他描述信息。

{
  "name": "webhere",
  "version": "0.0.7",
  "description": "Create a web server in the current directory.",
  "repository": {
    "type": "git",
    "url": "git@github.com:smallyard/webhere.git"
  },
  "author": "liuhongqiang <liuhongqiang@live.cn>",
  "license": "MIT",
  "bin": {
    "webhere": "./bin/webhere"
  },
  "keywords": [
    "webhere",
    "server",
    "web server"
  ],
  "engines": {
    "node": ">= 0.10"
  },
  "readmeFilename": "README.md"
}

2.bin文件,程序的入口。

#!/usr/bin/env node

var server = require("../src/server");

server.start();

3.web服务,server.js

var http = require("http");
var router = require("./router");
var render = require("./render");

function start() {
    function onRequest(request, response) {
        var routeResult = router.route(request.url);
        var responseInfo = render.getResponseInfo(routeResult);
        response.writeHead(responseInfo.status, {"Content-Type": responseInfo.contentType});
        response.write(responseInfo.content);
        response.end();
    }
    http.createServer(onRequest).listen(9000);
    console.log("Server has started.");
    console.log("Server address: http://127.0.0.1:9000");
}

exports.start = start;

4.路由router.js

var fs = require("fs");
function route(path) {
    console.log("Origin path: " + path);
    if (path == "/") {
        return "htmlIndex";
    } else {
        path = "." + path;
        if (fs.existsSync(path) && fs.statSync(path).isFile()) {
            return path;
        } else {
            return "html404";
        }
    }
}

exports.route = route;

5.内容渲染,render.js

var fs = require("fs");
var contentTypes = require("./contentTypes");
var HTML_INDEX = require("./html/index").html;
var HTML_404 = require("./html/404").html;

function getResponseInfo(routeResult) {
    console.log("Result path: " + routeResult);

    var status = 200;
    var content = "";
    var contentType = "text/html";
    if (routeResult == "htmlIndex") {
        content = HTML_INDEX;
    } else if (routeResult == "html404") {
        status = 404;
        content = HTML_404;
    } else {
        content = fs.readFileSync(routeResult);
        contentType = getContentType(routeResult);
    }
    return {
        "status": status,
        "contentType": contentType,
        "content": content
    };
}

function getContentType(filePath) {
    var suffix = "";
    var pointIndex = filePath.lastIndexOf(".");
    if (pointIndex != -1) {
        suffix = filePath.substr(pointIndex);
    }
    if (contentTypes.hasOwnProperty(suffix)) {
        return contentTypes[suffix];
    } else {
        return contentTypes[".*"];
    }
}

exports.getResponseInfo = getResponseInfo;

最后,附上我从开源中国上抓取的content-type

{
  ".*": "application/octet-stream",
  ".tif": "application/x-tif",
  ".001": "application/x-001",
  ".301": "application/x-301",
  ".323": "text/h323",
  ".906": "application/x-906",
  ".907": "drawing/907",
  ".a11": "application/x-a11",
  ".acp": "audio/x-mei-aac",
  ".ai": "application/postscript",
  ".aif": "audio/aiff",
  ".aifc": "audio/aiff",
  ".aiff": "audio/aiff",
  ".anv": "application/x-anv",
  ".asa": "text/asa",
  ".asf": "video/x-ms-asf",
  ".asp": "text/asp",
  ".asx": "video/x-ms-asf",
  ".au": "audio/basic",
  ".avi": "video/avi",
  ".awf": "application/vnd.adobe.workflow",
  ".biz": "text/xml",
  ".bmp": "application/x-bmp",
  ".bot": "application/x-bot",
  ".c4t": "application/x-c4t",
  ".c90": "application/x-c90",
  ".cal": "application/x-cals",
  ".cat": "application/vnd.ms-pki.seccat",
  ".cdf": "application/x-netcdf",
  ".cdr": "application/x-cdr",
  ".cel": "application/x-cel",
  ".cer": "application/x-x509-ca-cert",
  ".cg4": "application/x-g4",
  ".cgm": "application/x-cgm",
  ".cit": "application/x-cit",
  ".class": "java/*",
  ".cml": "text/xml",
  ".cmp": "application/x-cmp",
  ".cmx": "application/x-cmx",
  ".cot": "application/x-cot",
  ".crl": "application/pkix-crl",
  ".crt": "application/x-x509-ca-cert",
  ".csi": "application/x-csi",
  ".css": "text/css",
  ".cut": "application/x-cut",
  ".dbf": "application/x-dbf",
  ".dbm": "application/x-dbm",
  ".dbx": "application/x-dbx",
  ".dcd": "text/xml",
  ".dcx": "application/x-dcx",
  ".der": "application/x-x509-ca-cert",
  ".dgn": "application/x-dgn",
  ".dib": "application/x-dib",
  ".dll": "application/x-msdownload",
  ".doc": "application/msword",
  ".dot": "application/msword",
  ".drw": "application/x-drw",
  ".dtd": "text/xml",
  ".dwf": "application/x-dwf",
  ".dwg": "application/x-dwg",
  ".dxb": "application/x-dxb",
  ".dxf": "application/x-dxf",
  ".edn": "application/vnd.adobe.edn",
  ".emf": "application/x-emf",
  ".eml": "message/rfc822",
  ".ent": "text/xml",
  ".epi": "application/x-epi",
  ".eps": "application/postscript",
  ".etd": "application/x-ebx",
  ".exe": "application/x-msdownload",
  ".fax": "image/fax",
  ".fdf": "application/vnd.fdf",
  ".fif": "application/fractals",
  ".fo": "text/xml",
  ".frm": "application/x-frm",
  ".g4": "application/x-g4",
  ".gbr": "application/x-gbr",
  ".": "application/x-",
  ".gif": "image/gif",
  ".gl2": "application/x-gl2",
  ".gp4": "application/x-gp4",
  ".hgl": "application/x-hgl",
  ".hmr": "application/x-hmr",
  ".hpg": "application/x-hpgl",
  ".hpl": "application/x-hpl",
  ".hqx": "application/mac-binhex40",
  ".hrf": "application/x-hrf",
  ".hta": "application/hta",
  ".htc": "text/x-component",
  ".htm": "text/html",
  ".html": "text/html",
  ".htt": "text/webviewhtml",
  ".htx": "text/html",
  ".icb": "application/x-icb",
  ".ico": "application/x-ico",
  ".iff": "application/x-iff",
  ".ig4": "application/x-g4",
  ".igs": "application/x-igs",
  ".iii": "application/x-iphone",
  ".img": "application/x-img",
  ".ins": "application/x-internet-signup",
  ".isp": "application/x-internet-signup",
  ".IVF": "video/x-ivf",
  ".java": "java/*",
  ".jfif": "image/jpeg",
  ".jpe": "application/x-jpe",
  ".jpeg": "image/jpeg",
  ".jpg": "application/x-jpg",
  ".js": "application/x-javascript",
  ".jsp": "text/html",
  ".la1": "audio/x-liquid-file",
  ".lar": "application/x-laplayer-reg",
  ".latex": "application/x-latex",
  ".lavs": "audio/x-liquid-secure",
  ".lbm": "application/x-lbm",
  ".lmsff": "audio/x-la-lms",
  ".ls": "application/x-javascript",
  ".ltr": "application/x-ltr",
  ".m1v": "video/x-mpeg",
  ".m2v": "video/x-mpeg",
  ".m3u": "audio/mpegurl",
  ".m4e": "video/mpeg4",
  ".mac": "application/x-mac",
  ".man": "application/x-troff-man",
  ".math": "text/xml",
  ".mdb": "application/x-mdb",
  ".mfp": "application/x-shockwave-flash",
  ".mht": "message/rfc822",
  ".mhtml": "message/rfc822",
  ".mi": "application/x-mi",
  ".mid": "audio/mid",
  ".midi": "audio/mid",
  ".mil": "application/x-mil",
  ".mml": "text/xml",
  ".mnd": "audio/x-musicnet-download",
  ".mns": "audio/x-musicnet-stream",
  ".mocha": "application/x-javascript",
  ".movie": "video/x-sgi-movie",
  ".mp1": "audio/mp1",
  ".mp2": "audio/mp2",
  ".mp2v": "video/mpeg",
  ".mp3": "audio/mp3",
  ".mp4": "video/mpeg4",
  ".mpa": "video/x-mpg",
  ".mpd": "application/vnd.ms-project",
  ".mpe": "video/x-mpeg",
  ".mpeg": "video/mpg",
  ".mpg": "video/mpg",
  ".mpga": "audio/rn-mpeg",
  ".mpp": "application/vnd.ms-project",
  ".mps": "video/x-mpeg",
  ".mpt": "application/vnd.ms-project",
  ".mpv": "video/mpg",
  ".mpv2": "video/mpeg",
  ".mpw": "application/vnd.ms-project",
  ".mpx": "application/vnd.ms-project",
  ".mtx": "text/xml",
  ".mxp": "application/x-mmxp",
  ".net": "image/pnetvue",
  ".nrf": "application/x-nrf",
  ".nws": "message/rfc822",
  ".odc": "text/x-ms-odc",
  ".out": "application/x-out",
  ".p10": "application/pkcs10",
  ".p12": "application/x-pkcs12",
  ".p7b": "application/x-pkcs7-certificates",
  ".p7c": "application/pkcs7-mime",
  ".p7m": "application/pkcs7-mime",
  ".p7r": "application/x-pkcs7-certreqresp",
  ".p7s": "application/pkcs7-signature",
  ".pc5": "application/x-pc5",
  ".pci": "application/x-pci",
  ".pcl": "application/x-pcl",
  ".pcx": "application/x-pcx",
  ".pdf": "application/pdf",
  ".pdx": "application/vnd.adobe.pdx",
  ".pfx": "application/x-pkcs12",
  ".pgl": "application/x-pgl",
  ".pic": "application/x-pic",
  ".pko": "application/vnd.ms-pki.pko",
  ".pl": "application/x-perl",
  ".plg": "text/html",
  ".pls": "audio/scpls",
  ".plt": "application/x-plt",
  ".png": "application/x-png",
  ".pot": "application/vnd.ms-powerpoint",
  ".ppa": "application/vnd.ms-powerpoint",
  ".ppm": "application/x-ppm",
  ".pps": "application/vnd.ms-powerpoint",
  ".ppt": "application/x-ppt",
  ".pr": "application/x-pr",
  ".prf": "application/pics-rules",
  ".prn": "application/x-prn",
  ".prt": "application/x-prt",
  ".ps": "application/postscript",
  ".ptn": "application/x-ptn",
  ".pwz": "application/vnd.ms-powerpoint",
  ".r3t": "text/vnd.rn-realtext3d",
  ".ra": "audio/vnd.rn-realaudio",
  ".ram": "audio/x-pn-realaudio",
  ".ras": "application/x-ras",
  ".rat": "application/rat-file",
  ".rdf": "text/xml",
  ".rec": "application/vnd.rn-recording",
  ".red": "application/x-red",
  ".rgb": "application/x-rgb",
  ".rjs": "application/vnd.rn-realsystem-rjs",
  ".rjt": "application/vnd.rn-realsystem-rjt",
  ".rlc": "application/x-rlc",
  ".rle": "application/x-rle",
  ".rm": "application/vnd.rn-realmedia",
  ".rmf": "application/vnd.adobe.rmf",
  ".rmi": "audio/mid",
  ".rmj": "application/vnd.rn-realsystem-rmj",
  ".rmm": "audio/x-pn-realaudio",
  ".rmp": "application/vnd.rn-rn_music_package",
  ".rms": "application/vnd.rn-realmedia-secure",
  ".rmvb": "application/vnd.rn-realmedia-vbr",
  ".rmx": "application/vnd.rn-realsystem-rmx",
  ".rnx": "application/vnd.rn-realplayer",
  ".rp": "image/vnd.rn-realpix",
  ".rpm": "audio/x-pn-realaudio-plugin",
  ".rsml": "application/vnd.rn-rsml",
  ".rt": "text/vnd.rn-realtext",
  ".rtf": "application/x-rtf",
  ".rv": "video/vnd.rn-realvideo",
  ".sam": "application/x-sam",
  ".sat": "application/x-sat",
  ".sdp": "application/sdp",
  ".sdw": "application/x-sdw",
  ".sit": "application/x-stuffit",
  ".slb": "application/x-slb",
  ".sld": "application/x-sld",
  ".slk": "drawing/x-slk",
  ".smi": "application/smil",
  ".smil": "application/smil",
  ".smk": "application/x-smk",
  ".snd": "audio/basic",
  ".sol": "text/plain",
  ".sor": "text/plain",
  ".spc": "application/x-pkcs7-certificates",
  ".spl": "application/futuresplash",
  ".spp": "text/xml",
  ".ssm": "application/streamingmedia",
  ".sst": "application/vnd.ms-pki.certstore",
  ".stl": "application/vnd.ms-pki.stl",
  ".stm": "text/html",
  ".sty": "application/x-sty",
  ".svg": "text/xml",
  ".swf": "application/x-shockwave-flash",
  ".tdf": "application/x-tdf",
  ".tg4": "application/x-tg4",
  ".tga": "application/x-tga",
  ".tiff": "image/tiff",
  ".tld": "text/xml",
  ".top": "drawing/x-top",
  ".torrent": "application/x-bittorrent",
  ".tsd": "text/xml",
  ".txt": "text/plain",
  ".uin": "application/x-icq",
  ".uls": "text/iuls",
  ".vcf": "text/x-vcard",
  ".vda": "application/x-vda",
  ".vdx": "application/vnd.visio",
  ".vml": "text/xml",
  ".vpg": "application/x-vpeg005",
  ".vsd": "application/x-vsd",
  ".vss": "application/vnd.visio",
  ".vst": "application/x-vst",
  ".vsw": "application/vnd.visio",
  ".vsx": "application/vnd.visio",
  ".vtx": "application/vnd.visio",
  ".vxml": "text/xml",
  ".wav": "audio/wav",
  ".wax": "audio/x-ms-wax",
  ".wb1": "application/x-wb1",
  ".wb2": "application/x-wb2",
  ".wb3": "application/x-wb3",
  ".wbmp": "image/vnd.wap.wbmp",
  ".wiz": "application/msword",
  ".wk3": "application/x-wk3",
  ".wk4": "application/x-wk4",
  ".wkq": "application/x-wkq",
  ".wks": "application/x-wks",
  ".wm": "video/x-ms-wm",
  ".wma": "audio/x-ms-wma",
  ".wmd": "application/x-ms-wmd",
  ".wmf": "application/x-wmf",
  ".wml": "text/vnd.wap.wml",
  ".wmv": "video/x-ms-wmv",
  ".wmx": "video/x-ms-wmx",
  ".wmz": "application/x-ms-wmz",
  ".wp6": "application/x-wp6",
  ".wpd": "application/x-wpd",
  ".wpg": "application/x-wpg",
  ".wpl": "application/vnd.ms-wpl",
  ".wq1": "application/x-wq1",
  ".wr1": "application/x-wr1",
  ".wri": "application/x-wri",
  ".wrk": "application/x-wrk",
  ".ws": "application/x-ws",
  ".ws2": "application/x-ws",
  ".wsc": "text/scriptlet",
  ".wsdl": "text/xml",
  ".wvx": "video/x-ms-wvx",
  ".xdp": "application/vnd.adobe.xdp",
  ".xdr": "text/xml",
  ".xfd": "application/vnd.adobe.xfd",
  ".xfdf": "application/vnd.adobe.xfdf",
  ".xhtml": "text/html",
  ".xls": "application/x-xls",
  ".xlw": "application/x-xlw",
  ".xml": "text/xml",
  ".xpl": "audio/scpls",
  ".xq": "text/xml",
  ".xql": "text/xml",
  ".xquery": "text/xml",
  ".xsd": "text/xml",
  ".xsl": "text/xml",
  ".xslt": "text/xml",
  ".xwd": "application/x-xwd",
  ".x_b": "application/x-x_b",
  ".sis": "application/vnd.symbian.install",
  ".sisx": "application/vnd.symbian.install",
  ".x_t": "application/x-x_t",
  ".ipa": "application/vnd.iphone",
  ".apk": "application/vnd.android.package-archive",
  ".xap": "application/x-silverlight-app"
}

三、 总结

很简单。

源码发布在github:

https://github.com/smallyard/webhere

npm:

travis:

请嘲讽(✿◡‿◡)

 

写一个 nodejs npm应用 - webhere的更多相关文章

  1. linux下面配置安装nodejs+npm

    linux下 多亏这一篇文章= =我就卡死在文章所说的这个点里 附大牛链接:http://blog.sitearth.com/nodejs%E4%B8%8A%E4%BD%BF%E7%94%A8mong ...

  2. 怎么样写一个能告诉你npm包名字是否被占用的工具

    事情是这样的: 因为我经常会写一些npm包,但是有时候我写完一个包,npm publish 的时候却被提示说包名字被占用了,要不就改名字,要不就加scope,很无奈.npm 命令行可以通过 npm v ...

  3. 用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具

    用 nodejs 写一个命令行工具 :创建 react 组件的命令行工具 前言 上周,同事抱怨说 react 怎么不能像 angular 那样,使用命令行工具来生成一个组件.对呀,平时工作时,想要创建 ...

  4. 通过npm写一个cli命令行工具

    前言 如果你想写一个npm插件,如果你想通过命令行来简化自己的操作,如果你也是个懒惰的人,那么这篇文章值得一看. po主的上一篇文章介绍了定制自己的模版,但这样po主还是不满足啊,项目中我们频繁的需要 ...

  5. 从零开始写一个npm包及上传

    最近刚好自己需要写公有npm包及上传,虽然百度上资料都能找到,但是都是比较零零碎碎的,个人就来整理下,如何从零开始写一个npm包及上传. 该篇文件只记录一个大概的流程,一些细节没有记录. tips:  ...

  6. 我想写一个前端开发工具(一):在npm发布模块

    有必要说说我为什么要开始写这个,正文从下面的第一条开始 我最近忙于公司的项目,一直没有抽出时间来写文章.本来想每个月写一片文章,保质保量,无奈上个月没有坚持. 这段时间有点忙,主要是由于公司业务调整, ...

  7. 从零开始写一个npm包,一键生成react组件(偷懒==提高效率)

    前言 最近写项目开发新模块的时候,每次写新模块的时候需要创建一个组件的时候(包含组件css,index.js,组件js),就只能会拷贝其他组件修改名称 ,但是写了1-2个后发现效率太低了,而且极容易出 ...

  8. 80行代码教你写一个Webpack插件并发布到npm

    1. 前言 最近在学习 Webpack 相关的原理,以前只知道 Webpack 的配置方法,但并不知道其内部流程,经过一轮的学习,感觉获益良多,为了巩固学习的内容,我决定尝试自己动手写一个插件. 这个 ...

  9. [NodeJS]使用Node.js写一个简单的在线聊天室

    声明:教程来自<Node即学即用>.源代码案例均出自此书.博文仅为个人学习笔记. 第一步:创建一个聊天server. 首先,我们先来写一个Server: var net = require ...

随机推荐

  1. PL/SQL远程备份和恢复Oracle数据库

    (转自:http://blog.csdn.net/huchunfu/article/details/25165901) 在客户端远程备份的文件保存在数据库所在主机上,不会直接拷贝到客户端.—————— ...

  2. 使用Spring MVC 实现 国际化

    使用Spring MVC 实现 国际化     博客分类: Spring   1. 版本 Spring 3.1   2. 配置 LocaleResolver     LocaleResolver 是指 ...

  3. Linux系统管理命令之权限管理

    对于一个目录来说,x权限:可以cd进去 对于目录: 读:看 执行:进去 写:写操作 rw权限没有意义 umask 022     特殊权限: suid sgid 2种情况:对于文件:类似于suid对于 ...

  4. linux关于文件的那些事儿

    一个文件的权限对于系统的安全来说是很重要的,linux是一个支持多任务多用户的系统,我们都不希望一些自己的文件被别人看到或者修改! 对于一个文件的权限我们可以用 ls -l 命令来查看,例如: [ro ...

  5. Linux 文件常见类型

  6. speex进行音频去噪

    应用speex进行音频去噪,speex功能很强大,因为opus的出现,用speex进行编码/解码的人几乎没有了,但是用speex来进行降噪,去除回声,增益还是很多. 这里用speex进行音频去噪,主要 ...

  7. KVM 介绍(6):Nova 通过 libvirt 管理 QEMU/KVM 虚机 [Nova Libvirt QEMU/KVM Domain]

    学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...

  8. 新版Microsoft Azure Web管理控制台 - Microsoft Azure New Portal - (1)

    国际版Microsoft Azure的Preview Portal已经于12月2日正式GA,现在登录国际版的Microsoft Azure,默认就会进入Microsoft Azure New Port ...

  9. 网格弹簧质点系统模拟(Spring-Mass System by Euler Integration)

    弹簧质点模型是利用牛顿运动定律来模拟物体变形的方法.如下图所示,该模型是一个由m×n个虚拟质点组成的网格,质点之间用无质量的.自然长度不为零的弹簧连接.其连接关系有以下三种: 1.连接质点[i, j] ...

  10. HTML标签----图文详解(二)

    HTML标签超详细的图文演示再来一波~~~ 如果还没有看过昨天的福利的,那可要抓紧喽,传送门:HTML标签----图文详解 本文主要内容 列表标签 表格标签 框架标签及内嵌框架<iframe&g ...