項目准備
Web 服務器一般指網站服務器,是指駐留於因特網上某種類型計算機的程序,可以向瀏覽器等 Web 客戶端提供文檔,也可以放置網站文件,讓全世界瀏覽;可以放置數據文件,讓全世界下載。目前最主流的三個 Web 服務器是 Apache Nginx IIS,接下來主要是總結一下怎么使用node創建一個自己的靜態web服務器,在開始前,需要先准備一個前端項目:
http模塊
在前面的隨筆中有簡單的總結過http模塊和fs模塊:使用http創建簡單的服務時,能夠獲取用戶在地址欄中輸入的請求,並且每次都會額外的多一個favicon.ico請求。
而現在,要實現靜態web服務,就是要根據用戶的請求動態加載相關頁面資源並返回,首先要做的便是獲取用戶請求:
var http=require('http'); var fs=require('fs'); http.createServer(function(req,res){ var pathname=req.url; if(pathname=='/'){ pathname='/index.html'; } if(pathname!='/favicon.ico'){ fs.readFile('static/'+pathname,function(err,data){ if(err){ console.log('404'); }else{ res.writeHead(200,{"Content-Type":"text/html;charset='utf-8'"}); res.write(data); res.end(); } }) } }).listen(8001);
在上面的代碼中,首先使用http創建了一個服務,然后在第一個if語句中,添加了一個默認請求(默認加載頁面),在第二個if主要是先過濾每次請求中的favicon.ico請求,然后根據不同的請求,加載static頁面下的不同頁面。
當用戶請求http://localhost:8001/時,先執行了第一個if,請求變為了http://localhost:8001/index.html,進入第二個if,去static文件夾中找到index.html並返回,但是,此時和期望的結果是不一樣的,這是因為,在index.html中,有很多其他類型的請求
當請求了index.html后,就會自動觸發這些請求,根據上面這些請求分別是css和js,需要添加不同的頭文件,但是在上面的例子中,全部都是添加統一的頭文件,自然顯示就會有問題。
文件類型
從上面的例子看,根據不同的文件類型來添加不同的頭文件,主要是需要獲取請求的后綴名,然后根據后綴名來添加頭文件。
要獲取后綴名,需要使用到path模塊
獲取到后綴名以后,就可以在01.js的基礎上面,動態添加頭文件了,首先新建一個getmime.js文件,用於根據后綴名返回頭文件類型,然后在01.js的基礎上新建02.js
var http=require('http'); var fs=require('fs'); var path=require('path'); var mimeModel=require('./model/getmime.js'); http.createServer(function(req,res){ var pathname=req.url; if(pathname=='/'){ pathname='/index.html'; } var extname=path.extname(pathname); if(pathname!='/favicon.ico'){ fs.readFile('static/'+pathname,function(err,data){ if(err){ console.log('404'); fs.readFile('static/404.html',function(error,data404){ if(error){ console.log(error); } res.writeHead(404,{"Content-Type":"text/html;charset='utf-8'"}); res.write(data404); res.end(); /*結束響應*/ }) }else{ var mime=mimeModel.getMime(extname); /*獲取文件類型*/ res.writeHead(200,{"Content-Type":""+mime+";charset='utf-8'"}); res.write(data); res.end(); /*結束響應*/ } }) } }).listen(8001);
正確獲取請求文件
現在,看上去好像已經基本實現了預期的效果,但是,下面這種請求就會出錯了:
按照正常邏輯,上面的地址還是請求的index.html,只是后面多加了參數而已,但是在上面02.js里面確實這樣的結果
也就是說,在有參數的時候,上面的方法時行不通的,所以,我們還需要借助url模塊來正確解析出請求地址中的文件(03.js)
var http=require('http'); var fs=require('fs'); var path=require('path'); var url=require('url'); var mimeModel=require('./model/getmime.js'); http.createServer(function(req,res){ var pathname=url.parse(req.url).pathname; console.log(pathname) if(pathname=='/'){ pathname='/index.html'; } var extname=path.extname(pathname); console.log(extname); if(pathname!='/favicon.ico'){ fs.readFile('static/'+pathname,function(err,data){ if(err){ console.log('404'); fs.readFile('static/404.html',function(error,data404){ if(error){ console.log(error); } res.writeHead(404,{"Content-Type":"text/html;charset='utf-8'"}); res.write(data404); res.end(); /*結束響應*/ }) }else{ var mime=mimeModel.getMime(extname); /*獲取文件類型*/ res.writeHead(200,{"Content-Type":""+mime+";charset='utf-8'"}); res.write(data); res.end(); /*結束響應*/ } }) } }).listen(8001);
各種文件類型
在02.js中,為了實現效果,根據不同的請求添加不同的頭文件,只是列舉幾種常見的文件類型,但在實際項目中的文件類型,遠不止這些,所以這里提供了一份更完整的文件類型所對應的頭文件:
mime.json
然后再新建文件getmimefromfile.js,添加一個方法,傳入文件后綴名后,返回對應的頭文件:
最后,在03.js的基礎上面引入該文件,完善代碼
var http=require('http'); var fs=require('fs'); var path=require('path'); var url=require('url'); var mimeModel=require('./model/getmimefromfile.js'); http.createServer(function(req,res){ var pathname=url.parse(req.url).pathname; if(pathname=='/'){ pathname='/index.html'; /*默認加載的首頁*/ } var extname=path.extname(pathname); if(pathname!='/favicon.ico'){ fs.readFile('static/'+pathname,function(err,data){ if(err){ fs.readFile('static/404.html',function(error,data404){ if(error){ console.log(error); } res.writeHead(404,{"Content-Type":"text/html;charset='utf-8'"}); res.write(data404); res.end(); }) }else{ var mime=mimeModel.getMime(fs,extname); /*獲取文件類型*/ res.writeHead(200,{"Content-Type":""+mime+";charset='utf-8'"}); res.write(data); res.end(); } }) } }).listen(8001);
代碼下載:點這里 提取碼(2f71)
文章整理自it營相關教程