/** * 靜態服務器功能:核心模塊HTTP * 初步實現服務器功能 */ const http = require('http'); //建立服務器實例對象 let server = http.createServer(); //綁定請求事件 server.on('request',(req,res) => { res.end('hello'); }); //監聽端口 訪問地址:localhost:3000 server.listen(3000); //========================================= http.createServer((req,res) => { res.end('ok'); }).listen(3000,'196.167.0.8',() => { //此時不能再用localhost訪問了,只能用IP地址:3000 console.log('running...'); });
/** * 處理請求路徑的分發 * 由於訪問localhost:3000、localhost:3000/index.html、localhost:3000/about.html等頁面時,顯示內容都同樣 * 1.req對象是Class:http.IncomingMessage的實例對象 * 2.res對象是Class:http.ServerResponse的實例對象 */ const http = require('http'); http.createServer((req,res) => { //req.url能夠獲取URL中的路徑(端口以後的路徑) //res.end(req.url); if(req.url.startsWith('/index')){ //write向客戶端相應內容,可屢次寫回,拼寫到一塊兒 res.write('hello'); res.write('welcome'); //end用來完成響應,能夠帶參數也能夠不帶,只能執行一次 res.end('index'); }else if(req.url.startsWith('/about')){ res.end('about'); }else{ res.end('no content'); } }).listen(3000,'196.167.0.8',() => { //此時不能再用localhost訪問了,只能用IP地址:3000 console.log('running...'); });
/** * 響應完整的頁面信息,先建立多個文件,利用路徑分發功能分別對不一樣頁面進行響應 */ const http = require('http'); const path = require('path'); const fs = require('fs'); //根據路徑讀取文件的內容,而且相應到瀏覽器 //抽取出來做爲單獨的一個方法 let readFile = (url,res) => { fs.readFile(path.join(__dirname,url),'utf8',(err,fileContent) => { if(err){ res.end('server error'); }else{ res.end(fileContent); } }); } //處理路徑分發 http.createServer((req,res) => { if(req.url.startsWith('/index')){ readFile('index.html',res); }else if(req.url.startsWith('/about')){ readFile('about.html',res); }else if(req.url.startsWith('/list')){ readFile('list.html',res); }else{ //設置相應類型和編碼,不然沒有響應投不能正常跳轉 res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf8'}); res.end('404 not found'); } }).listen(3000,'196.167.0.8',() => { //此時不能再用localhost訪問了,只能用IP地址:3000 console.log('running...'); });
隨着頁面分支愈來愈多,上述方式不夠靈活,應該根據url去獲取這個文件(利用req.url獲取到的是端口號後面的路徑)html
/** * 路徑分發的改進 */ const http = require('http'); const path = require('path'); const fs = require('fs'); //引入mime模塊,做用就是根據url的後綴,返回對應的Content-Type,或者你傳遞Content-Type,它返回對應的文件類型的後綴 //安裝mime模塊:npm install mime --save const mime = require('mime'); //處理路徑分發 http.createServer((req,res) => { fs.readFile(path.join(__dirname,req.url),(err,fileContent) => { if(err){ //沒有找到對應文件 //設置響應頭信息,避免出現亂碼 res.writeHead(404,{ 'Content-Type':'text/plain;charset=utf8' }); //res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf8'}); res.end('頁面丟失了'); }else{ //獲取請求文件的後綴 //默認類型: //let dType = 'text/html'; //let ext = path.extname(req.url); //console.log(ext); //console.log(mime[ext]); //console.log(mime.getType(path.join(__dirname,req.url))); //若是喲請求的文件後綴合理,就獲取到標準的響應格式 //若是mime裏面存在這個後綴,則覆蓋默認的後綴類型 //這種作法不行,一直處在默認類型,進不了這個循環 /* if(mime[ext]){ dType = mime[ext]; } */ //mime.getType(filePath) let dType = mime.getType(path.join(__dirname,req.url)); //若是是文本類型,則須要設置其編碼類型 if(dType.startsWith('text')){ dType += ';charset=utf8' } //設置響應頭信息 res.writeHead(200,{'Content-Type':dType}); res.end(fileContent); } }); }).listen(3000,() => { console.log('running...'); });
爲了對靜態資源服務器這個功能進行優化,能夠將這部分功能抽取成一個獨立的模塊,方便之後使用。npm
/** * 抽取模塊:01.js文件 */ const http = require('http'); const path = require('path'); const fs = require('fs'); const mime = require('mime'); //root表示文件的根路徑 exports.staticServer = (req,res,root) => { fs.readFile(path.join(root,req.url),(err,fileContent) => { if(err){ //沒有找到對應文件 //設置響應頭信息,避免出現亂碼 res.writeHead(404,{ 'Content-Type':'text/plain;charset=utf8' }); //res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf8'}); res.end('頁面丟失了'); }else{let dType = mime.getType(path.join(__dirname,req.url)); //若是是文本類型,則須要設置其編碼類型 if(dType.startsWith('text')){ dType += ';charset=utf8' } //設置響應頭信息 res.writeHead(200,{'Content-Type':dType}); res.end(fileContent); } }); }
/** * 測試模塊:02.js文件 */ const http = require('http'); const path = require('path'); const ss = require('./03.js'); http.createServer((req,res) => { ss.staticServer(req,res,path.join(__dirname)); }).listen(3000,() => { console.log('running...'); });