NodeJS中的http模块

尽管expresskoa等优秀的库已经对http模块进行了封装,但是针对NodeJS的Web开发,还是很有必须了解一下http模块。

<!--more-->

参考:

http模块的属性和方法可以分成客户端和服务端两部分,另外还有一个常量属性STATUS_CODES保存了http响应报文起始行的状态码和相关描述。

1. 客户端

http.ClientRequest
抽象为一个客户端请求对象,常用的有write等方法,也有data,end等事件。 此外可以把客户端请求对象当作一个只读数据流来访问请求体数据。

http.request
用于客户端发出请求,返回的是一个http.ClientRequest的实例

let contents = "Hello World";

// 配置参数
let opt = {
    host: "localhost",
    path:'/',
    port:3000,
    method:'POST',
    headers:{
        'Content-Type':'application/x-www-form-urlencoded',
        'Content-Length':contents.length
    }
}

let req = http.request(opt,(res)=>{
    // res是请求返回结果
})

req.write(contents);
req.end();

http.get http.requestmethod:"GET的快捷方式,且不需要显示调用req.end()方法。之前的静态爬虫就是使用get来实现的。

注意,由于需要调用write向服务器发送数据,貌似并没有http.post的快捷方式哦

2. 服务端

2.1. http.Server

抽象为一个服务器对象,

let server = new http.Server();

/* 事件 */
server.on("request", requestListener);

server.on("conection",()=>{});

server.on("close",()=>{})

/* 方法 */
server.listen(888);

server.close();

由于request事件使用的太频繁了,http模块上直接注册了一个createServer方法作为该事件的快捷方式。

http.createServer(requestListener)

2.2. requestListener

function requestListener(req,res){
    // req是http.IncomingMessage的一个实例 
    // res是http.ServerResponse的一个实例
    // todo
}

requestListener是一个回调函数,它将会自动加入到request 事件的监听队列。当request事件触发时,Event-Loop会将该事件处理函数放入执行队列,当前面的队列函数执行完毕之后,就会执行该事件处理函数。

这里需要明白的是:Node中所有的代码都是一个一个从执行队列中拿出来执行的。这些执行都是在工作线程上(Event Loop本身可以认为在一个独立的线程中,我们一般不提这个线程,而将node称呼为一个单线程的执行环境),所有的回调都是在一个工作线程上运行。

2.3. http.IncomingMessage

抽象为服务器接受到的请求对象(假装是http.ServerRequest这样命名的东西),主要定义了data,end,close这几个事件,常用的属性有header,url,httpVersion,statusCode

function requestListener(req,res){
    let msg = "";
    req.on("data",(chunk)=>{
        msg += chunk;
    })
    req.on("error",(err)=>{
        console.log('something wrong');
    })

    req.on("end",()=>{
        // todo
    })
}

IncomingMessage对象可以由http.Serverhttp.ClientRequest创建。

2.4. http.ServerResponse

抽象为一个服务器响应对象,常用的方法有writeHead,write,end等,事件貌似只有close

req.on("end",()=>{
    res.writeHead(200, {"Content-type":"text/plain"});
    res.write("hello, I have recive:" + msg);
    res.end();
})

3. Express中的封装

3.1. 基础

epxress在http模块的基础上进行了封装

let express = require('express');
let app = express();

// 启动服务器
let server = app.listen(3000, function () {
    console.log("server is running~");
});

// 监听路由
app.get('/', function (req, res) {
    res.send("hello");
});

3.2. 路由

路由可以看作是HTTP请求的CGI,由后台定义路由的处理逻辑,当接收到相应请求后就将请求转移到对应的路由处理方法。

app.post('/posttest', function (req, res) {
    res.send("post test");
    // 根据请求数据做点事
});

常用的路由方法有get,post,delete等多种,其中,all是一种特殊的方法,它的作用是对于一个路径上的所有请求加载中间件。

4. 小结

尽管一直想使用NodeJS进行web开发,却一直没有机会。这里整理了一点http模块的东西,接下来打算好好看一看Express,写个小项目练练手。

《同构JavaScript应用开发》读书笔记 HTTP协议之安全(五)