亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Node.js靜態(tài)服務(wù)器的實現(xiàn)方法

 更新時間:2018年02月28日 16:24:51   作者:Cris_冷崢子  
這篇文章主要介紹了Node.js靜態(tài)服務(wù)器的實現(xiàn)方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下

當(dāng)你輸入一個url時,這個url可能對應(yīng)服務(wù)器上的一個資源(文件)也可能對應(yīng)一個目錄。 So服務(wù)器會對這個url進(jìn)行分析,針對不同的情況做不同的事。 如果這個url對應(yīng)的是一個文件,那么服務(wù)器就會返回這個文件。 如果這個url對應(yīng)的是一個文件夾,那么服務(wù)器會返回這個文件夾下包含的所有子文件/子文件夾的列表。 以上,就是一個靜態(tài)服務(wù)器所主要干的事。

但真實的情況不會像這么簡單, 我們所拿到的url可能是錯誤的,它所對應(yīng)的文件或則文件夾或許根本不存在, 又或則有些文件和文件夾是被系統(tǒng)保護(hù)起來的是隱藏的,我們并不想讓客戶端知道。 因此,我們就要針對這些特殊情況進(jìn)行一些不同的返回和提示。

再者,當(dāng)我們真正返回一個文件前,我們需要和客戶端進(jìn)行一些協(xié)商。 我們需要知道客戶端能夠接受的語言類型、編碼方式等等以便針對不同瀏覽器進(jìn)行不同的返回處理。 我們需要告訴客戶端一些關(guān)于返回文件的額外信息,以便客戶端能更好的接收數(shù)據(jù): 文件是否需要緩存,該怎樣緩存? 文件是否進(jìn)行了壓縮處理,該以怎樣的方式解壓? 等等...

至此,我們已經(jīng)初步了解了一個靜態(tài)服務(wù)器所主要做的幾乎所有事情, let's go!

實現(xiàn)

項目目錄

static-server/
|
| - bin/
| | - start # 批處理文件
|  
|
| - src/
| | - App.js # main文件
| | - Config.js # 默認(rèn)配置
|
|
·- package.json

配置文件

要啟動一個服務(wù)器,我們需要知道這個服務(wù)器的啟動時的端口號和靜態(tài)服務(wù)器的工作目錄

let config = {
 host:'localhost' //提升用
 ,port:8080 //服務(wù)器啟動時候的默認(rèn)端口號
 ,path:path.resolve(__dirname,'..','test-dir') //靜態(tài)服務(wù)器啟動時默認(rèn)的工作目錄
}

整體框架

注意

事件函數(shù)中的this默認(rèn)指向綁定的對象(這里是小server),這里修改成了Server這個大對象,以便調(diào)用在回調(diào)函數(shù)中調(diào)用Server下的方法。

class Server(){
 constructor(options){
  /* === 合并配置參數(shù) === */
  this.config = Object.assign({},config,options)
 }
 start(){
  /* === 啟動http服務(wù) === */
  let server = http.createServer();
  server.on('request',this.request.bind(this)); 
  server.listen(this.config.port,()=>{
   let url = `${this.config.host}:${this.config.port}`;
   console.log(`server started at ${chalk.green(url)}`)
  })
 }
 async request(req,res){
  /* === 處理客戶端請求,決定響應(yīng)信息 === */
  // try
  //如果是文件夾 -> 顯示子文件、文件夾列表
  //如果是文件 -> sendFile()
  // catch
  //出錯 -> sendError()
 }
 sendFile(){
  //對要返回的文件進(jìn)行預(yù)處理并發(fā)送文件
 }
 handleCache(){
  //獲取和設(shè)置緩存相關(guān)信息
 }
 getEncoding(){
  //獲取和設(shè)置編碼相關(guān)信息
 }
 getStream(){
  //獲取和設(shè)置分塊傳輸相關(guān)信息
 }
 sendError(){
  //錯誤提示
 }
}
module.exports = Server;

request請求處理

獲取url的 pathname ,和 服務(wù)器本地的工作根目錄地址 進(jìn)行拼接,返回一個 filename 利用filename和 stat方法 檢測是文件還是文件夾

是文件夾, 利用 readdir方法 返回該文件夾下的列表,將列表包裝成一個對象組成的數(shù)組 然后結(jié)合handlebar將數(shù)組數(shù)據(jù)編譯到模板中,最后返回這個模板給客戶端

是文件, 將req、res、statObj、filepath傳遞給 sendFile ,接下來交由sendFile處理

async request(req,res){
 let pathname = url.parse(req.url);
 if(pathname == '/favicon.ico') return;
 let filepath = path.join(this.config.root,pathname);
 try{
  let statObj = await stat(filepath);
  if(statObj.isDirectory()){
   let files = awaity readdir(filepath);
   files.map(file=>{
    name:file
    ,path:path.join(pathname,file)
   });
   // 讓handlebar 拿著數(shù)去編譯模板
   let html = this.list({
    title:pathname
    ,files
   })
   res.setHeader('Content-Type','text/html');
   res.end(html);
  }else{
   this.sendFile(req,res,filepath,statObj);
  }
 }catch(e){
  this.sendError(e,req,res);
 }
}

[tip] 我們將 request 方法 async 化,這樣我們就能像寫同步代碼一樣寫異步

方法

sendFile

涉及緩存、編碼、分段傳輸?shù)裙δ?/p>

sendFile(){
 if(this.handleCache(req,res,filepath,statObj)) return; //如果走緩存,則直接返回。
 res.setHeader('Content-type',mime.getType(filepath)+';charset=utf-8');
 let encoding = this.getEncoding(req,res); //獲取瀏覽器能接收的編碼并選擇一種
 let rs = this.getStream(req,res,filepath,statObj); //支持?jǐn)帱c續(xù)傳
 if(encoding){
  rs.pipe(encoding).pipe(res);
 }else{
  rs.pipe(res);
 }
}

handleCache

緩存處理時要注意的是,緩存分為強制緩存和對比緩存,且強制緩存的優(yōu)先級是高于相對緩存的。 也就是說,當(dāng)強制緩存生效的時候并不會走相對緩存,不會像服務(wù)器發(fā)起請求。 但一旦強制緩存失效,就會走相對緩存,如果 文件標(biāo)識 沒有改變,則相對緩存生效, 客戶端仍然會去緩存數(shù)據(jù)拿取數(shù)據(jù),所以強制緩存和相對緩存并不沖突。 強制緩存和相對緩存一起使用時,能在減少服務(wù)器的壓力的同事又保持請求數(shù)據(jù)的及時更新。

另外需要注意的是,如果同時設(shè)置了兩種相對緩存的文件標(biāo)識,必須要兩種都沒有改變時,緩存才生效。

handleCache(req,res,filepath,statObj){
 let ifModifiedSince = req.headers['if-modified-since']; //第一次請求是不會有的
 let isNoneMatch = req.headers['is-none-match'];
 res.setHeader('Cache-Control','private,max-age=30');
 res.setHeader('Expires',new Date(Date.now()+30*1000).toGMTString()); //此時間必須為GMT
 
 let etag = statObj.size;
 let lastModified = statObj.ctime.toGMTString(); //此時間格式可配置
 res.setHeader('Etag',etag);
 res.setHeader('Last-Modified',lastModified);
 
 if(isNoneMatch && isNoneMatch != etag) return false; //若是第一次請求已經(jīng)返回false
 if(ifModifiedSince && ifModifiedSince != lastModified) return false;
 if(isNoneMatch || ifModifiedSince){
 // 說明設(shè)置了isNoneMatch或則isModifiedSince且文件沒有改變
  res.writeHead(304);
  res.end();
  return true;
 }esle{
  return false;
 }
}

getEncoding

從請求頭中拿取到瀏覽器能接收的編碼類型,利用正則匹配匹配出最前面那個, 創(chuàng)建出對應(yīng)的zlib實例返回給sendFile方法,以便在返回文件時進(jìn)行編碼。

getEncoding(req,res){
 let acceptEncoding = req.headers['accept-encoding'];
 if(/\bgzip\b/.test(acceptEncoding)){
  res.setHeader('Content-Encoding','gzip');
  return zlib.createGzip();
 }else if(/\bdeflate\b/.test(acceptEncoding)){
  res.setHeader('Content-Encoding','deflate');
  return zlib.createDeflate();
 }else{
  return null;
 }
}

getStream

分段傳輸,主要利用的是請求頭中的 req.headers['range'] 來確認(rèn)要接收的文件是從哪里開始到哪里結(jié)束,然而真正拿到這部分?jǐn)?shù)據(jù)是通過 fs.createReadStream 來讀取到的。

getStream(req,res,filepath,statObj){
 let start = 0;
 let end = startObj.size - 1;
 let range = req.headers['range'];
 if(range){
  res.setHeader('Accept-Range','bytes');
  res.statusCode = 206; //返回整個數(shù)據(jù)的一塊
  let result = range.match(/bytes = (\d*)-(\d*)/); //不可能有小數(shù),網(wǎng)絡(luò)傳輸?shù)淖钚挝粸橐粋€字節(jié)
  if(result){
   start = isNaN(result[1])?0:parseInt(result[1]);
   end = isNaN(result[2])?end:parseInt(result[2])-1; //因為readstream的索引是包前又包后故要減去1
  }
 }
 return fs.createReadStream(filepath,{
  start,end
 });
}

包裝成命令行工具

我們可以像在命令行中輸入 npm start 啟動一個dev-server一樣自定義一個啟動命令來啟動我們的靜態(tài)服務(wù)器。

大體實現(xiàn)的思路是: 在 packge.json 中的 bin 屬性下配置一個啟動命令和這個執(zhí)行這個命令的文件的路徑。 然后我們需要準(zhǔn)備一個批處理文件,在文件中引入我們的靜態(tài)服務(wù)器文件,讓我們的服務(wù)器跑起來 然后將這個文件 node link 即可。

總結(jié)

以上所述是小編給大家介紹的Node.js靜態(tài)服務(wù)器的實現(xiàn)方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • node.JS的crypto加密模塊使用方法詳解(MD5,AES,Hmac,Diffie-Hellman加密)

    node.JS的crypto加密模塊使用方法詳解(MD5,AES,Hmac,Diffie-Hellman加密)

    本文將詳細(xì)介紹node.JS的加密模塊crypto實現(xiàn)MD5,AES,Hmac,Diffie-Hellman加密的詳解方法,需要的朋友可以參考下
    2020-02-02
  • node.js基于dgram數(shù)據(jù)報模塊創(chuàng)建UDP服務(wù)器和客戶端操作示例

    node.js基于dgram數(shù)據(jù)報模塊創(chuàng)建UDP服務(wù)器和客戶端操作示例

    這篇文章主要介紹了node.js基于dgram數(shù)據(jù)報模塊創(chuàng)建UDP服務(wù)器和客戶端操作,結(jié)合實例形式分析了node.js使用dgram數(shù)據(jù)報模塊創(chuàng)建UDP服務(wù)器和客戶端,以及進(jìn)行UDP廣播、組播相關(guān)操作技巧,需要的朋友可以參考下
    2020-02-02
  • benny簡單框架benchmark功能使用

    benny簡單框架benchmark功能使用

    這篇文章主要為大家介紹了benny簡單框架benchmark功能使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 基于NodeJS的前后端分離的思考與實踐(一)全棧式開發(fā)

    基于NodeJS的前后端分離的思考與實踐(一)全棧式開發(fā)

    這個話題最近被討論得比較多,阿里有些BU也在進(jìn)行一些嘗試。討論了很久之后,我們團(tuán)隊決定探索一套基于NodeJS的前后端分離方案,過程中有一些不斷變化的認(rèn)識以及思考,記錄在這里,也希望看到的同學(xué)參與討論,幫我們完善。
    2014-09-09
  • Node.js+pm2+ssh2模塊實現(xiàn)簡單的自動化部署腳本

    Node.js+pm2+ssh2模塊實現(xiàn)簡單的自動化部署腳本

    本文將介紹如何使用Node.js和ssh2模塊實現(xiàn)一個簡單的部署腳本,將本地的項目文件上傳到遠(yuǎn)程服務(wù)器上,我們將使用dotenv模塊來管理環(huán)境變量,以及child_process模塊來執(zhí)行命令行操作
    2023-10-10
  • Node Puppeteer圖像識別實現(xiàn)百度指數(shù)爬蟲的示例

    Node Puppeteer圖像識別實現(xiàn)百度指數(shù)爬蟲的示例

    本篇文章主要介紹了Node Puppeteer圖像識別實現(xiàn)百度指數(shù)爬蟲的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • Node.js自定義對象事件的監(jiān)聽與發(fā)射

    Node.js自定義對象事件的監(jiān)聽與發(fā)射

    這篇文章介紹了Node.js自定義對象事件監(jiān)聽與發(fā)射的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • 使用Node.js自動生成帶動態(tài)圖表的Word文檔

    使用Node.js自動生成帶動態(tài)圖表的Word文檔

    在現(xiàn)代軟件開發(fā)中,動態(tài)生成?Word?文檔是一項非常常見的需求,本文將結(jié)合Node.js和ECharts實現(xiàn)自動生成帶動態(tài)圖表的Word文檔,感興趣的可以了解下
    2024-03-03
  • NodeJS感知和控制自身進(jìn)程的運行環(huán)境和狀態(tài)

    NodeJS感知和控制自身進(jìn)程的運行環(huán)境和狀態(tài)

    NodeJS可以感知和控制自身進(jìn)程的運行環(huán)境和狀態(tài),也可以創(chuàng)建子進(jìn)程并與其協(xié)同工作,這使得NodeJS可以把多個程序組合在一起共同完成某項工作,并在其中充當(dāng)膠水和調(diào)度器的作用,和進(jìn)程管理相關(guān)的API單獨介紹起來比較枯燥,這里從一些典型的應(yīng)用場景出發(fā)
    2024-01-01
  • Ubuntu 16.04 64位中搭建Node.js開發(fā)環(huán)境教程

    Ubuntu 16.04 64位中搭建Node.js開發(fā)環(huán)境教程

    如果想要在Ubuntu 16.04上安裝Node.js的話,這篇文章對你來說肯定很重要。Node.js從本質(zhì)上來說就是一個運行在服務(wù)端上的封裝好了輸入輸出流的javascript程序。本文給大家詳細(xì)介紹了在Ubuntu 16.04 64位搭建Node.js開發(fā)環(huán)境的步驟,有需要的朋友們可以參考學(xué)習(xí)。
    2016-10-10

最新評論