最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Node.js一行代碼實(shí)現(xiàn)靜態(tài)文件服務(wù)器的方法步驟

 更新時(shí)間:2019年05月07日 09:09:22   作者:windyfancylv  
這篇文章主要介紹了Node.js一行代碼實(shí)現(xiàn)靜態(tài)文件服務(wù)器的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

靜態(tài)文件服務(wù)器實(shí)現(xiàn)

nodejs不僅僅可以用來寫服務(wù)端接口,用來做靜態(tài)文件服務(wù)器替代nginx的功能, 也是分分鐘可以搞定的。 話不多說,先上代碼:

var server=http.createServer(function (req,res){
 fs.createReadStream(Path.resolve(__dirname,"."+req.url)).pipe(res);
})

在項(xiàng)目根目錄建一個(gè)hello.html文件測(cè)試一下 hello.html內(nèi)容如下:

<h1>hello,world</h1>

node app.js運(yùn)行,打開瀏覽器訪問一下: http://localhost/hello.html

我們?cè)倩仡^審視一下代碼,的確就只有這么簡(jiǎn)單,這要?dú)w功于node Stream類 pipe方法的強(qiáng)大,fs.createReadStream讀取本地文件創(chuàng)建一個(gè)可讀流(ReadStream類的實(shí)例),再使用pipe導(dǎo)流到res響應(yīng)流,res是一個(gè)http.ServerResponse類的實(shí)例,是一個(gè)可寫流,繼承自 Stream類

http.ServerResponse類的繼承關(guān)系如下:

安全性考慮

上述代碼實(shí)現(xiàn)靜態(tài)文件服務(wù)器后,意味著項(xiàng)目根目錄下所有的文件(遞歸)都可以通過瀏覽器直接訪問和下載了,這樣會(huì)帶來一些安全性的問題,想想看,你的服務(wù)器端代碼和配置文件都能通過瀏覽器直接下載了,因此需要在代碼里加一些限制,例如只能訪問特定的目錄下的文件和特定擴(kuò)展名的文件,這樣還不夠,參考OWasp Top 10安全風(fēng)險(xiǎn)(第4條-不安全的對(duì)象直接引用),攻擊者仍然可以通過../../目錄回溯的方法訪問到其它目錄,對(duì)于訪問路徑中包含..的也要全部過濾掉。

實(shí)現(xiàn)mine type

mime type是指http 響應(yīng)頭中的content-type字段,它決定了瀏覽器如何解析文件,是直接當(dāng)做純文件顯示(text/plain),還是做為html文件渲染(text/html),或者當(dāng)做二進(jìn)制文件下載,沒有輸出正確的mine type,可能導(dǎo)致圖片文件無法顯示,字體文件無效,視頻文件無法播放的問題。要實(shí)現(xiàn)起來也十分簡(jiǎn)單,只需要做一個(gè)映射表,不同文件擴(kuò)展名,在響應(yīng)頭的content-type字段中輸出對(duì)應(yīng)的mine type就行了。

完整代碼如下:

const http=require("http");
const Path=require("path");
const fs=require("fs");

var server=http.createServer(function (req,res){
 const fileName=Path.resolve(__dirname,"."+req.url);
 const extName=Path.extname(fileName).substr(1);

 if (fs.existsSync(fileName)) { //判斷本地文件是否存在
  var mineTypeMap={
   html:'text/html;charset=utf-8',
   htm:'text/html;charset=utf-8',
   xml:"text/xml;charset=utf-8",
   png:"image/png",
   jpg:"image/jpeg",
   jpeg:"image/jpeg",
   gif:"image/gif",
   css:"text/css;charset=utf-8",
   txt:"text/plain;charset=utf-8",
   mp3:"audio/mpeg",
   mp4:"video/mp4",
   ico:"image/x-icon",
   tif:"image/tiff",
   svg:"image/svg+xml",
   zip:"application/zip",
   ttf:"font/ttf",
   woff:"font/woff",
   woff2:"font/woff2",

  }
  if (mineTypeMap[extName]) {
   res.setHeader('Content-Type', mineTypeMap[extName]);
  }
  var stream=fs.createReadStream(fileName);
  stream.pipe(res);
 }

 
})
server.listen(80);

實(shí)現(xiàn)gzip

對(duì)于文本類型的文件,如html,js,css,采用gzip壓縮可以大幅減少傳輸量,提升服務(wù)器傳輸性能,當(dāng)然這會(huì)損耗一點(diǎn)服務(wù)器的cpu性能做為代價(jià),如果客戶端瀏覽器支持gzip壓縮,則會(huì)在請(qǐng)求頭的accept-encoding中攜帶gzip關(guān)鍵字,用node自帶的zlib類就可以實(shí)現(xiàn)gzip壓縮了,只要在stream.pip實(shí)多加一層,先導(dǎo)流到gzip流,再導(dǎo)出到res流,當(dāng)然,還要在響應(yīng)頭中添加Content-Encoding為gzip,這樣瀏覽器才能正確識(shí)別到http body是采用gzip算法壓縮的,并進(jìn)行自動(dòng)解壓縮。

代碼如下:

const zlib = require('zlib');

if (req.headers["accept-encoding"].indexOf("gzip")>=0 && (extName=="js" || extName=="css" || extName=="html"))) {
  res.setHeader('Content-Encoding', "gzip");
  const gzip = zlib.createGzip();
  stream.pipe(gzip).pipe(res);
 }

客戶端緩存

http協(xié)議的緩存協(xié)商流程比較長,最終在響應(yīng)頭中生成expire(絕對(duì)時(shí)間)和cache-control(相對(duì)時(shí)間)兩個(gè)用于控制緩存過期時(shí)間的參數(shù),瀏覽器下次請(qǐng)求該文件時(shí),分為以下幾種情況:

  • 如果沒到過期時(shí)間,瀏覽器不會(huì)請(qǐng)求文件直接讀緩存
  • 如果已到過期時(shí)間,則會(huì)在請(qǐng)求頭中l(wèi)ast-modified字段攜帶文件的最后修改日期,如果對(duì)比時(shí)間戳與服務(wù)器文件一致,則HTTP 返回 304: Not Modified
  • 如果按下f5刷新,會(huì)在請(qǐng)求頭中if-modified-since字段中攜帶緩存的過期時(shí)間,如果對(duì)比時(shí)間戳與服務(wù)器文件一致,則HTTP 返回 304: Not Modified
  • ctrl+f5刷新,請(qǐng)求頭中攜帶 cache-control: no-cache,強(qiáng)制禁用緩存。重新下載文件

邏輯分支較多,但都是日期比對(duì),搞清楚緩存協(xié)商過程比較容易寫出來,有興趣的同學(xué)可以自行實(shí)現(xiàn)

高性能靜態(tài)文件服務(wù)器優(yōu)化

如果要做一個(gè)高性能的靜態(tài)文件服務(wù)器僅實(shí)現(xiàn)gzip和緩存協(xié)商是不夠的,涉及到本地文件的頻繁讀取,高并發(fā)下I/O必定成為瓶頸,考慮到服務(wù)器上的文件是很少更新的, 可以用Buffer把文件流緩存到內(nèi)存中,每次請(qǐng)求時(shí)先在內(nèi)存中查找匹配項(xiàng),如果命中了直接從內(nèi)存中返回,避免了讀取磁盤,gzip也不用壓縮了,直接用壓縮好的文件流返回,可以成倍的大幅提升性能。當(dāng)然如果文件太多了,內(nèi)存也會(huì)飆升,需要考慮淘汰算法,只緩存訪問次數(shù)高的文件,剔除低訪問量的文件。

采用fs.watch監(jiān)控目錄文件的變化,如果文件有更新,則刪掉緩存。

小結(jié)

Node.js 內(nèi)置的pipe方法可以非常簡(jiǎn)便的實(shí)現(xiàn)將服務(wù)器本地文件輸出到http 響應(yīng)流中,gzip壓縮也同樣可以通過pipe實(shí)現(xiàn),再配合輸出mine type 實(shí)現(xiàn)的靜態(tài)服務(wù)器已經(jīng)可以滿足一般業(yè)務(wù)的使用。如果要實(shí)現(xiàn)高性能的靜態(tài)文件服務(wù)器,還需要實(shí)現(xiàn)客戶端緩存、服務(wù)端緩存功能(本文提供了思路,按圖索驥也非難事)。

最后,推薦一下個(gè)人的開源項(xiàng)目, node.js web開發(fā)框架,已包含本文靜態(tài)文件服務(wù)器的功能 webcontext: https://github.com/windyfancy/webcontext

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺析node中間件及實(shí)現(xiàn)一個(gè)簡(jiǎn)單的node中間件

    淺析node中間件及實(shí)現(xiàn)一個(gè)簡(jiǎn)單的node中間件

    這篇文章主要介紹了淺析node中間件及實(shí)現(xiàn)一個(gè)簡(jiǎn)單的node中間件,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • 使用Node.js find-up在父目錄中高效尋找文件與目錄

    使用Node.js find-up在父目錄中高效尋找文件與目錄

    find-up 是一個(gè)小巧但功能強(qiáng)大的 Node.js 包,它能幫助我們實(shí)現(xiàn)這一需求,本文將深入探究如何使用 find-up 進(jìn)行有效搜索,并結(jié)合豐富的代碼演示幫助大家快速掌握其用法,需要的朋友可以參考下
    2024-05-05
  • node.js支持多用戶web終端實(shí)現(xiàn)及安全方案

    node.js支持多用戶web終端實(shí)現(xiàn)及安全方案

    這篇文章主要介紹了node.js支持多用戶web終端實(shí)現(xiàn)方案以及web終端安全性保證的解決方法,一起學(xué)習(xí)參考下。
    2017-11-11
  • Node.js中.pfx后綴文件的處理方法

    Node.js中.pfx后綴文件的處理方法

    這篇文章主要介紹了Node.js中.pfx后綴文件的處理方法,文中介紹的很詳細(xì),對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。
    2017-03-03
  • Centos7 中安裝 Node.js v4.4.4

    Centos7 中安裝 Node.js v4.4.4

    我一直對(duì)學(xué)習(xí)Node.js比較感興趣。這是一個(gè)Java平臺(tái)的服務(wù)器端編程 ,它允許開發(fā)人員在服務(wù)器編寫Java代碼,并且有許多CentOS的用戶正努力學(xué)習(xí)這個(gè)語言的開發(fā)環(huán)境。這正是我想做這個(gè)教程的目的。
    2016-11-11
  • nodeJs實(shí)現(xiàn)基于連接池連接mysql的方法示例

    nodeJs實(shí)現(xiàn)基于連接池連接mysql的方法示例

    這篇文章主要介紹了nodeJs實(shí)現(xiàn)基于連接池連接mysql的方法,結(jié)合具體實(shí)例形式分析了nodejs連接池操作mysql數(shù)據(jù)庫連接的實(shí)現(xiàn)與使用技巧,需要的朋友可以參考下
    2018-02-02
  • Nodejs如何復(fù)制文件

    Nodejs如何復(fù)制文件

    這篇文章主要為大家詳細(xì)介紹了Nodejs如何復(fù)制文件的過程,感興趣的小伙伴們可以參考一下
    2016-03-03
  • Node版本切換不成功的問題解決

    Node版本切換不成功的問題解決

    使用 Node.js 和 npm 安裝 Taro 等工具時(shí),可能會(huì)遇到一些環(huán)境問題或配置錯(cuò)誤,本文就來介紹一下Node版本切換不成功的問題解決,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-12-12
  • 淺談Node新版本13.2.0正式支持ES Modules特性

    淺談Node新版本13.2.0正式支持ES Modules特性

    這篇文章主要介紹了淺談Node新版本13.2.0正式支持ES Modules特性,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 開箱即用的Node.js+Mysql模塊封裝實(shí)現(xiàn)詳解

    開箱即用的Node.js+Mysql模塊封裝實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了開箱即用的Node.js+Mysql模塊封裝實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01

最新評(píng)論

上高县| 工布江达县| 怀宁县| 咸丰县| 西畴县| 杭锦旗| 信阳市| 郑州市| 兴山县| 平南县| 湖南省| 牡丹江市| 临沧市| 新巴尔虎左旗| 朝阳区| 博客| 诸城市| 闽清县| 余干县| 屯门区| 固镇县| 常德市| 青田县| 自贡市| 定远县| 宜兰市| 普定县| 新乐市| 招远市| 景德镇市| 神木县| 阿荣旗| 万宁市| 宁陕县| 鄂伦春自治旗| 环江| 正蓝旗| 延庆县| 牟定县| 香港| 蒙山县|