拼多多版http-server

我叫呂胖胖發表於2018-09-21

1 前言

不知從什麼時候開始,本胖就喜歡用一個叫做http-server的中介軟體用來在啟動一個靜態的伺服器以及解決跨域問題。

http-server 是一個簡單的零配置命令列HTTP伺服器, 基於 nodeJs。

現在,本胖要自己從零開始實現一個http-server中介軟體,暫且取名為lpp-http-server,用以致敬偉大的http-server。

2 所用npm包

一般來說寫一箇中介軟體會依賴其他的輔助包,lpp-http-server也不例外。這裡本胖主要依賴瞭如下的npm包。

1.colors--用於在控制檯輸出五顏六色的命令2.commander--提供了使用者命令列輸入和引數解析強大功能3.http-proxy--轉發請求4.pug--模板複製程式碼

3 Server類

這個類是整個lpp-http-server的核心,作用就是實現一個靜態伺服器。主要包含了以下幾個方法。

1.handleRequest——對請求的處理2.sendDir--渲染目錄資訊3.sendFile——獲取檔案資訊4.proxy——轉發介面5.sendError——傳送錯資訊6.start——啟動複製程式碼

下面就來一一介紹這個方法

3.1 handleRequest

async handleRequest(req, res) { 
const {
dir, proxyUrl
} = this.config;
let {
pathname
} = url.parse(req.url);
pathname = decodeURIComponent(pathname);
const fileUrl = path.join(dir, pathname);
try {
// 判斷當前路徑是檔案 還是資料夾 const statObj = await stat(fileUrl);
if (statObj.isDirectory()) {
// 資料夾則輸出對應的目錄 this.sendDir(req, res, pathname, fileUrl);

} else {
// 檔案則直接輸出內容 this.sendFile(req, res, statObj, fileUrl);

}
} catch (e) {
// 轉發請求 if (proxyUrl) {
this.proxy(req, res, proxyUrl);

} else {
this.sendError(req, res);

}
}
}複製程式碼

上面是handleRequest方法的全部程式碼,可以看出,主要就是對請求的不同情況的處理,主要處理了以下幾種情況。

1.請求的是檔案地址2.請求的是檔案目錄地址3.請求的地址404複製程式碼

然後對這幾種情況做了分別的處理。

3.2 sendDir

  // 獲取資料夾目錄  async sendDir(req, res, pathname, fileUrl) { 
// 讀取當前訪問的目錄下的所有內容 readdir 陣列 把陣列渲染回頁面 res.setHeader('Content-Type', 'text/html;
charset=utf8'
) let dirs = await readdir(fileUrl);
dirs = dirs.map(item =>
({
name: item, // 因為點選第二層時 需要帶上第一層的路徑,所有拼接上就ok了 href: path.join(pathname, item)
})) // 渲染template.html中需要填充的內容,name是當前檔案目錄,arr為當前資料夾下的目錄陣列 const str = pug.render(this.template, {
arr: dirs
});
// 響應中返回填充內容 res.end(str);

}複製程式碼

上面的sendDir方法是用來獲取當前目錄的,主要用了readdir方法來讀取一個目錄的內容,然後迴圈輸出,這裡用了pug當做html模板。pug檔案的主要內容如下

doctype htmlhtml  head    meta(charset="utf-8")    meta(name="renderer", content="webkit")    meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")    title lvpp-http-server  body    block content    div    - for (var x = 0;
x <
arr.length;
x++) div a(href=arr[x]['href'])= arr[x]['name']複製程式碼

3.3 sendFile

  // 獲取檔案資訊  sendFile(req, res, statObj, fileUrl) { 
// 管道讀寫操作,將fs.createReadStream(p)的內容寫入到res // return fs.createReadStream(fileUrl).pipe(res);
fs.readFile(fileUrl, 'utf-8', function (err, data) {
if (err) {
throw err;

} res.end(data);

});

}複製程式碼

sendFile方法是用來獲取檔案資訊的,當然最好是用createReadStream方法,他們的區別可以參考node官網。

3.4 proxy

  // 代理  proxy(req, res, proxyUrl) { 
delete req.headers.host;
var proxy = httpProxy.createProxyServer({
});
proxy.web(req, res, {
target: proxyUrl
});

}複製程式碼

這裡用了http-proxy包進行了轉發,需要注意下面這行程式碼

delete req.headers.host;
複製程式碼

一開始沒有這行程式碼,請求轉發是不行的。

3.5 start

  // 啟動  start() { 
const server = http.createServer(this.handleRequest.bind(this));
server.listen(this.config.port, this.config.host, () =>
{
console.log(`server start http://${this.config.host
}
:${colors.green(this.config.port)
}
`);
// 代理 if (this.config.proxyUrl) {
console.log(colors.yellow('Unhandled requests will be served from: ' + this.config.proxyUrl));

}
});

}複製程式碼

啟動的方法主要是啟動一個靜態伺服器http.createServer,然後對該伺服器的一些配置。

4 啟動指令碼

這個指令碼主要是對一些命令的操作,這裡用的是commander這個模組。

#! /usr/bin/env node// 告訴作業系統執行這個指令碼的時候,呼叫 / usr / bin下的node直譯器;const Server = require('../src/index.js');
// 匯入Serverconst commander = require('commander');
// 匯入命令列模組const {
version
} = require('../package.json');
// 讀取package.json的版本// 配置命令列commander .option('-p,--port <
n>
'
, 'config port') // 配置埠 .option('-o,--host [value]', 'config hostname') // 配置主機名 .option('-d,--dir [value]', 'config directory') // 配置訪問目錄 .option('-P,--proxyUrl [value]', 'config proxy') // 配置轉發地址 .version(version, '-v,--version') // 展示版本 .parse(process.argv);
const server = new Server(commander);
server.start();
複製程式碼

在寫好程式碼之後,我們想要的當然是執行一個自定義命令,就可以執行我們的包了,不用每次都是node ./bin/www.js。

這時候一步配置即可,找到整個專案的package.json檔案,加入以下資訊

"bin": { 
"lpp-http-server": "bin/www.js"
},複製程式碼

上面這段命令的意思就是用lpp-http-server這個命令去代替執行node bin/www.js,寫好命令後,還需要在整個目錄下執行

npm link複製程式碼

然後你就會發現你在你電腦任何地方都可以執行lpp-http-server,生成一個靜態伺服器了,效果如下

拼多多版http-server
拼多多版http-server
拼多多版http-server

本文完

來源:https://juejin.im/post/5ba44daef265da0a9e530aab

相關文章