一箫攀、瀏覽器發(fā)送請(qǐng)求
1、用戶輸入網(wǎng)址
http://127.0.0.1/
2违崇、瀏覽器根據(jù)請(qǐng)求轉(zhuǎn)變HTTP的請(qǐng)求包
GET / HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
二阿弃、服務(wù)器接收到請(qǐng)求
1诊霹、http模塊里實(shí)例化的server對(duì)象,server對(duì)象監(jiān)聽每一次瀏覽器發(fā)送過來的請(qǐng)求恤浪,每次的請(qǐng)求都會(huì)觸發(fā)request事件
this.server.on("request",(req,res)=>{})
2畅哑、將HTTP的請(qǐng)求包轉(zhuǎn)換成req的請(qǐng)求對(duì)象,并且傳入到請(qǐng)求事件觸發(fā)的函數(shù)中水由。
3荠呐、會(huì)創(chuàng)建生成一個(gè)res響應(yīng)對(duì)象,這個(gè)對(duì)象可以幫助我們快速的實(shí)現(xiàn)HTTP的響應(yīng)砂客。
三泥张、解析請(qǐng)求路徑,調(diào)用不同的頁面渲染函數(shù)
1鞠值、正則匹配方式進(jìn)行對(duì)路徑的匹配媚创。
2、以匹配的正則字符串作為KEY彤恶,找到需要調(diào)用執(zhí)行的渲染函數(shù)
//循環(huán)匹配正則路徑
for(let key in this.reqEvent){
let regStr = key
let reg = new RegExp(regStr,'igs');
if(reg.test(req.url)){
this.reqEvent[key](req,res);
resState = true
break;
}
}
3钞钙、調(diào)用頁面的執(zhí)行函數(shù),執(zhí)行模板渲染
app.on('/movies/[01]',(req,res)=>{}) //這里的箭頭函數(shù)即為真正匹配到的頁面執(zhí)行的函數(shù)
4声离、調(diào)用模板的渲染函數(shù)
res.render(movies[index],'./template/index1.html')
5芒炼、執(zhí)行渲染函數(shù)
function render(options,path) {
fs.readFile(path,{encoding:"utf-8",flag:"r"},(err,data)=>{
if(err){
console.log(err)
}else{
try{
data = replaceArr(data,options)
data = replaceVar(data,options)
}catch(error){
console.log(error)
}
this.end(data)
}
})
}
6、數(shù)組變量的替換
function replaceArr(data,options){
//匹配循環(huán)的變量,并且替換循環(huán)的內(nèi)容
let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\%endfor\%\}/igs
while(result = reg.exec(data)){
let strKey = result[1].trim();//提取變量時(shí)术徊,去掉左右兩邊的空格
//通過key值獲取數(shù)組的內(nèi)容
let strValueArr = options[strKey]
let listStr = ""
strValueArr.forEach((item,i) => {
//替換每一項(xiàng)內(nèi)容里的變量
listStr = listStr + replaceVar(result[2],{"item":item})
});
data = data.replace(result[0],listStr)
}
return data
}
7本刽、單個(gè)變量的替換
function replaceVar(data,options) {
//匹配普通的變量,并且替換內(nèi)容
let reg = /\{\{(.*?)\}\}/igs
let result;
while (result = reg.exec(data)){
//去除兩邊的空白
let strKey = result[1].trim();
//options.item
let strValue = eval('options.'+strKey);//執(zhí)行字符串作為JS表達(dá)式,并將計(jì)算出來的結(jié)果返回
data = data.replace(result[0],strValue)
}
return data
}
四赠涮、如果是請(qǐng)求靜態(tài)文件子寓,那么就按照靜態(tài)文件的形式輸出
1、首先判斷是否響應(yīng)過,如果沒有響應(yīng)過笋除,可以判斷是否為靜態(tài)文件斜友,如果是靜態(tài)文件就正常的輸出
2、否則就輸出404
if(!resState){
try{
if(pathObj.dir==this.staticDir){
res.setHeader("content-type",this.getContentType(pathObj.ext))
let rs = fs.createReadStream('./static/'+pathObj.base)
rs.pipe(res)
}else{
res.setHeader("content-type","text/html;charset=utf-8")
res.end("<h1>404!頁面找不到</h1>")
}
}catch(error){
console.log(error)
}
}
五垃它、RES響應(yīng)對(duì)象將res設(shè)置的內(nèi)容最終轉(zhuǎn)化成http的響應(yīng)包
HTTP/1.1 200 OK
content-type: text/html;charset=utf-8
Date: Thu, 23 Jul 2020 12:17:19 GMT
Connection: keep-alive
Content-Length: 53
正文內(nèi)容
六鲜屏、瀏覽器解析響應(yīng)包,并將html渲染在頁面上