Node 搭建一个静态资源服务器的实现

2020-06-17 05:51:05易采站长站整理


// server/route.js
const fs = require('fs')

module.exports = function (request, response, filePath){
fs.stat(filePath, (err, stats) => {
if (err) {
response.statusCode = 404
response.setHeader('content-type', 'text/plain')
response.end(`${filePath} is not a file`)
return;
}
if (stats.isFile()) {
response.statusCode = 200
response.setHeader('content-type', 'text/plain')
fs.createReadStream(filePath).pipe(response)
}
else if (stats.isDirectory()) {
fs.readdir(filePath, (err, files) => {
response.statusCode = 200
response.setHeader('content-type', 'text/plain')
response.end(files.join(','))
})
}
})
}

其中

fs.createReadStream()
读取文件流,
pipe()
是分段读取文件到内存,优化高并发的情况。

修改之前的 http server ,引入上面新建的 route.js 作为响应函数:


// server/http.js
const http = require('http')
const path = require('path')

const config = require('./config')
const route = require('./route')

const server = http.createServer((request, response) => {
let filePath = path.join(config.root, request.url)
route(request, response, filePath)
})

server.listen(config.port, config.host, () => {
const addr = `http://${config.host}:${config.port}`
console.info(`server started at ${addr}`)
})

再次执行

$ node server/http.js
如果是文件夹则显示目录:

如果是文件则直接输出:

成熟的静态资源服务器 anywhere,深入理解 nodejs 作者写的。

三、util.promisify 优化 fs 异步

我们注意到

fs.stat()
fs.readdir()
都有 callback 回调。我们结合 Node 的 util.promisify() 来链式操作,代替地狱回调。

util.promisify 只是返回一个 Promise 实例来方便异步操作,并且可以和 async/await 配合使用,修改 route.js 中 fs 操作相关的代码:


// server/route.js
const fs = require('fs')
const util = require('util')

const stat = util.promisify(fs.stat)
const readdir = util.promisify(fs.readdir)

module.exports = async function (request, response, filePath) {
try {
const stats = await stat(filePath)
if (stats.isFile()) {
response.statusCode = 200
response.setHeader('content-type', 'text/plain')
fs.createReadStream(filePath).pipe(response)