框架流程

2020-07-23  本文已影响0人  十八句

一、浏览器发送请求

1、用户输入网址
http://127.0.0.1/
2、浏览器根据请求转变HTTP的请求包
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

二、服务器接收到请求

1、http模块里实例化的server对象,server对象监听每一次浏览器发送过来的请求,每次的请求都会触发request事件
this.server.on("request",(req,res)=>{})
2、将HTTP的请求包转换成req的请求对象,并且传入到请求事件触发的函数中。
3、会创建生成一个res响应对象,这个对象可以帮助我们快速的实现HTTP的响应。

三、解析请求路径,调用不同的页面渲染函数

1、正则匹配方式进行对路径的匹配。
2、以匹配的正则字符串作为KEY,找到需要调用执行的渲染函数
//循环匹配正则路径
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、调用页面的执行函数,执行模板渲染
app.on('/movies/[01]',(req,res)=>{}) //这里的箭头函数即为真正匹配到的页面执行的函数
4、调用模板的渲染函数
res.render(movies[index],'./template/index1.html')
5、执行渲染函数
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、数组变量的替换
function replaceArr(data,options){
    //匹配循环的变量,并且替换循环的内容
    let reg = /\{\%for \{(.*?)\} \%\}(.*?)\{\%endfor\%\}/igs
    while(result = reg.exec(data)){
        let strKey = result[1].trim();//提取变量时,去掉左右两边的空格
        //通过key值获取数组的内容
        let strValueArr = options[strKey]
        let listStr = ""
        strValueArr.forEach((item,i) => {
            //替换每一项内容里的变量
            listStr = listStr + replaceVar(result[2],{"item":item})
        });
        data = data.replace(result[0],listStr)
    }
    return data
}
7、单个变量的替换
function replaceVar(data,options) {
    //匹配普通的变量,并且替换内容
    let reg = /\{\{(.*?)\}\}/igs
    let result;
    while (result = reg.exec(data)){
        //去除两边的空白
        let strKey = result[1].trim();
        //options.item
        let strValue = eval('options.'+strKey);//执行字符串作为JS表达式,并将计算出来的结果返回
        data = data.replace(result[0],strValue)
    }
    return data
}

四、如果是请求静态文件,那么就按照静态文件的形式输出

1、首先判断是否响应过,如果没有响应过,可以判断是否为静态文件,如果是静态文件就正常的输出
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响应对象将res设置的内容最终转化成http的响应包

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

正文内容

六、浏览器解析响应包,并将html渲染在页面上

上一篇 下一篇

猜你喜欢

热点阅读