美文网首页
HTTP模块

HTTP模块

作者: 萘小蒽 | 来源:发表于2020-03-11 16:59 被阅读0次

    NodeHTTP模块包含对http处理的封装。在node中,HTTP服务继承自TCP服务器(net模块),它能够与多个客户端保持连接,由于其采用时间驱动的形式,并不为每一个连接创建额外的线程或进程,保持很低的内存占用,所以能实现高并发。


    HTTP服务于tcp服务模型的比较

    区别

    • 在开启Keepalive后,一个TCP会话可以用于多次请求和响应。
    • 理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连 接之前,TCP 连接都将被一直保持下去。
    • HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”.
    • TCP服务以connection为单位进行服务,HTTP服务以request为单位进行服务。
    • HTTP模块即是将connection到request的过程进行的封装。
      联系
    • http是要基于TCP连接基础上的,TCP就是单纯建立连接,不涉及任何我们需要请求的实际数据,简单的传输。
      http是用来收发数据,即实际应用上来的。
    • 客户端和应用服务器建立TCP连接之后,就需要用http协议来传送数据了,HTTP协议简单来说,还是请求,确认,连接。

    HTTP流程

    HTTP模块将连接所用套接字的读写抽象为ServerRequestServerResponse对象,它们对应请求和响应操作。在请求产生的过程中,HTTP模块拿到连接中传来的数据,调用二进制模块http_parser进行解析,在解析完请求报文得我爆头后,触发request事件,调用用户的业务逻辑。

    HTTP流程的示意图

    HTTP模块产生请求的过程
    上面的处理程序对应到的代码就是下面响应Hello World这部分,代码如下:
    function(req, res){
      res.wirteHead(200,{'content-type': 'textt/plain'});
      res.end(' Hello World ')
    }
    

    HTTP请求

    对于TCP连接的读操作,http模块将其封装为serverRequest对象。
    通过curl获取http服务的报文,报文的头部会通过http_parser进行解析。报文如下:

    > GET / HTTP/1.1
    > Host: 127.0.0.1:1337
    > User-Agent: curl/7.55.1
    > Accept: */*
    

    报文头第一行 GET / HTTP/1.1被解析之后分解为如下属性。

    • req.method属性:值为GET,是为请求方法,常见的请求方法有GET、POST、DELETE、PUT、CONNECT等几种。
    • req.url属性:值为/
    • req.httpVersion属性:值为1.1

    其余报文都是很规律的key:value格式,被解析后放置在req.headers属性上传递给业务逻辑以供调用,如下:

    headers:{
      User-Agent: curl/7.55.1,
      Host: 127.0.0.1:1337,
      Accept: */*
    }
    

    报文体部分则抽象为一个制度对象,如果业务逻辑需要读取报文体中的数据,则要在这个数据流结束后才能进行操作,如下:

    function (req, res) {
        console.log(req.headers);
        var buffers = [];
        req.on('data', function (trunk) {
            buffers.push(trunk);
        }).on('end', function () {
            var buffer = Buffer.concat(buffers);
            //TODO
            res.end('hello world')
        });
    }
    

    HTTP请求对象和HTTP响应对象是相对较底层的封装,web框架如ConnectExpress都是在这两个对象基础上进行搞成封装完成的。

    HTTP响应

    HTTP响应对象相对简单一些,它封装了对底层连接的写操作,可以将其看成一个可写的流对象。它影响响应报文头部信息的API为res.setHeader()和res.weiteHead():

    res.writeHead(200, {'Content-Type':'text/plain'});
    

    其分为setHeader()writeHead()两个步骤。它在http模块封装下,实际生成如下报文:

    < HTTP/1.1 200 OK
    < Content-Type: text/plain
    
    • 可调用setHeader进行多次设置,但只有调用writeHead后,报文才会写入到连接中。

    HTTP模块会自动帮你设置一些头信息:

    < Date: Wed, 11 Mar 2020 08:32:20 GMT
    < Connection: keep-alive
    < Transfer-Encoding: chunked
    
    • 报文体部分则是调用res.write()res.end()方法实现。
    • res.end()res.write()差别在于end()会先调用write()发送数据,然后发送信号告知服务器这次响应结束。
    • 响应结束后,HTTP服务器可能会将当前的链接用于下一个请求,或者关闭链接。
    • 报头是在报文体发送前发送,一旦开始了数据的发送,writeHeadsetHeader将不会在生效。
    • 服务端在处理业务逻辑时无论是否发生异常,务必在结束时调用res.end的方式结束请求,以防客户端一直处于等待的状态。
    • 可通过延迟res.end的方式实现客户端与服务端之间的长度连接,但是结束时务必关闭链接。

    相关文章

      网友评论

          本文标题:HTTP模块

          本文链接:https://www.haomeiwen.com/subject/zcwikhtx.html