對於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