对于http
的了解,之前只看下200
还有404
之类。稍微学习node
的http
后发现了不少平时应用的到但不易察觉的功能。 好比请求响应中的压缩,图片防盗链的应用等等。了解到应用node核心模块http
等能够搭建本地服务,小试一下~javascript
如今,就利用http搭建一个小巧的本地服务。css
|--my-server
| |--bin
| | |--www.js
| |--src
| | |--config.js
| | |--index.js
| | |--template.html
| |--public
| |--index.html
| |--index.css
| |--a
| |--test.txt
复制代码
www.js 作入口html
#! /usr/bin/env node
require('../src/index')
复制代码
#! /usr/bin/env node
为指定脚本的解释程序。java
这种写法主要是为了让你的程序在不一样的系统上都能适用。
#!/usr/bin/env node
会自动的在你的用户PATH变量中所定义的目录中寻找node来执行的。node
index.js 为项目主要内容,http在此引用并搭建服务。git
let http = require('http')
http.createServer(function(req,res){
res.end('hello world')
}).listen(3000)
复制代码
npm link
会绑定package.json
里bin
下的命令。docker
{
"bin": {
"run-server": "bin/www.js"
}
}
复制代码
执行npm link
结果,显示命令成功以www.js
为入口:npm
up to date in 0.143s
/usr/local/bin/run-server -> /usr/local/lib/node_modules/http-jyn-static/bin/www.js /usr/local/lib/node_modules/http-jyn-static -> /Users/jyn/work/study/june/static_server/jyn_server
复制代码
此时进行以下操做测试:json
run-server
,启动服务localhost://3002
hello world
添加配置文件config.js:api
module.exports = {
port: 3002,
host: 'localhost',
dir: public
}
复制代码
实现打开网页后能够将目录下的内容展现给用户,还能够进行对应的点击操做。
做为能够复用的静态服务,须要将server写成构造函数类型
class Server{
constructor(){
this.config = config
}
handleRequest(){
console.log(this)
}
start(){
let server = http.createServer(this.handleRequest.bind(this))// 让this指向当前的server
server.listen(config.port,config.host,()=>{
console.log(`server start http://${config.host}:${config.port}`)
})
}
}
复制代码
运行结果以下:
/usr/local/bin/node /Users/jyn/work/study/june/static_server/jyn_server/src/index.js
server start http://localhost:3002
复制代码
说明启动命令能够启动服务。 基本搭建结束,继续完善:
经过promisify方便书写代码,处理文件读取等异步问题
结合promisify,获取文件信息,可方便后面分析文件路径,读取文件等:
let stat = util.promisify(fs.stat);// promisify
let readdir = util.promisify(fs.readdir);
let p = path.join(dir, pathname);
let statObj = await stat(p);
复制代码
statObj.isDirectory()
根据目录类型还有文件类型进行相应处理; 经过读取当前访问的目录下的全部内容 readdir 数组,而后再把数组渲染回页面
if (statObj.isDirectory()) {
res.setHeader('Content-Type', 'text/html;charset=utf8')
let dirs = await readdir(p);
dirs = dirs.map(item=>({
name:item,
href:path.join(pathname,item)
}))
res.end(str);
} else {
this.sendFile(req, res, statObj, p);
}
复制代码
文件路径dirs结果为:
[{ name: 'a', href: '/a' },
{ name: 'test.txt', href: '/test.txt' },
{ name: 'index.css', href: '/index.css' },
{ name: 'index.html', href: '/index.html' } ]
复制代码
根据文件层级进行相应的拼接,点击第二层时 须要带上第一层的路径,能够经过直接拼接路径的方式:
dirs = dirs.map(item=>({
name:item,
href:path.join(pathname,item)
}))
复制代码
此时测试点击目录a,显示结果为:
[ { name: 'test.txt', href: '/a/test.txt' } ]
复制代码
<% '脚本' 标签,用于流程控制,无输出。
%> 通常结束标签
模板中javascript语句用特殊标签包裹:
<body>
<h2><%=name%></h2>
<%arr.forEach(item=>{%>
<li><a href="<%=item.href%>"><%=item.name%></a></li>
<%})%>
</body>
复制代码
根据ejs模板渲染数据方法ejs.render
进行解析,ejs.render()
用法为:
template(data);
// => 输出绘制后的 HTML 字符串
ejs.render(str, data, options);
// => 输出绘制后的 HTML 字符串
ejs.renderFile(filename, data, options, function(err, str){
// str => 输出绘制后的 HTML 字符串
});
复制代码
应用ejs.render渲染后,设置响应头为text/html
,让浏览器解析模板字符串并展现
res.setHeader('Content-Type', 'text/html;charset=utf8')
let str = ejs.render(this.template, {
name: `Index of ${pathname}`,
arr: dirs
});
res.end(str);
复制代码
效果如图:
返回文件的内容须要根据文件的不一样类型设置返回头,文件类型可应用第三方模块mime
, 经过mimelite.getType(...);
获取并读取文件内容:
res.setHeader('Content-Type', mime.getType(p) + ';charset=utf8');
fs.createReadStream(p).pipe(res);
复制代码
根据node核心模块 os, 根据不一样的操做系统实现不一样的打开方式:
The os.platform() method returns a string identifying the operating system platform as set during compile time of Node.js.
www.js
中添加
let os = require('os');
let {exec} = require('child_process')
if(os.platform() === 'win32'){
exec(`start http://${commander.host}:${commander.port}`);
}else{
exec(`open http://${commander.host}:${commander.port}`);
}
复制代码
此时操做之须要一步执行 run-server
,启动服务就好了,这时就会看到浏览器自动打开了localhost://3002
.
基本功能实现后,能够对请求添加缓存机制,文件请求格式gzip压缩等功能。比较简单,会在下篇关于请求头响应头应用的文章中做介绍。
npm ERR! publish Failed PUT 403
npm ERR! code E403
npm ERR! no_perms Private mode enable, only admin can publish this module: http-jyn-static
复制代码
修正方案: npm config set registry http://registry.npmjs.org
以后再执行一遍发包操做,成功:
➜ jyn_server git:(master) npm publish
+ http-jyn-static@1.0.0
复制代码
在一个拥有以下文件的目录进行静态服务安装:
|--test
| |--index.html
| |--config.js
| |--a
| |--read.txt
复制代码
安装
➜ test
npm install http-jyn-static
复制代码
启动服务
run-server
server start http://localhost:3002
复制代码
运行结果: 出现错误,由于件config.js中路径写死为public
文件夹,修改成: dir: process.cwd()
。
进行版本升级:
npm version minor
npm publish
再次更新package进行测试,成功打开文件夹列表:
欢迎你们批评指正~
Reference:
Author: Yanni Jia
Nickname: 很是兔
Email: 385067638@qq.com