详解Node Http模块
概述
node http 同时支持服务端和客户端功能
- http.createServer
- http.request
关联知识点:
- Stream可写或可读流,Buffer、fs、Stream之间的关系
- EventEmitter事件发射器,即发布订阅的关系
http模块的类、属性和方法
http模块中,有几个类,很多对象都是这些类的实例
- http.Server
- http.ServerResponse
- http.ClientRequest
- http.IncomingMessage
- http.Agent
http模块中,还有几个方法和属性
- http.METHODS
- http.STATUS_CODES
- http.globalAgent
- http.createServer()
- http.get()
- http.request()
http模块服务端的介绍
创建http服务器,从上面罗列的类和方法可以看出有2种方式
const http = require('http')
// 方法 1
const server = new http.Server()
server.on('request', (req, res) => {
res.end()
})
// 方法 2
const server = http.createServer((req, res) => {
res.end()
})
从上面可以得出以下结论
- createServer方法就是对
new http.Server()
的封装,其接收的回调函数,也就是事件request
的回调 - 它们都会得到
Server
类的实例 - 回调中,都会接收2个参数,
request
和response
,此时,request
是IncomingMessage
的实例,response
是ServerResponse
的实例
上面我们提到事件发射器,此处的Server
就是一个事件发射器,它发射的事件有:
- request 每次接收到一个请求时触发
- connect 每当客户端发送 HTTP
CONNECT
请求时触发 - connection 当新的 TCP 流被建立时触发,例如socket连接
- close
- clientError 如果客户端触发了一个 'error' 事件,则它会被传递到这里
- upgrade
- checkContinue
- checkExpectation
Server
类还有一些方法:
- server.listen() 创建服务器后,监听端口以启动连接
- server.close()
- server.setTimeout()
介绍完创建http服务实例的server对象,我们再来看看返回的2个对象IncomingMessage
的实例和ServerResponse
的实例
从上面创建http服务的代码中可以看到,我们会使用res
对象的方法去做一些事情,用以响应客户端的请求,它也是一个EventEmitter
。
关于响应体,我们知道有头部和实体,ServerResponse
对头部的操作:
- res.writeHead(statusCode[, statusMessage][, headers])
res.writeHead(200, 'OK', { 'Content-Type': 'text/plain' })
- res.setHeader(name, value)
- res.getHeader(name)
- res.removeHeader(name)
对实体的方法
- res.write(chunk[, encoding][, callback])
- chunk
String|Buffer
,当为字符串时,第二个参数指定字符串如何编码成字节流,encoding
默认为utf8
- chunk
- response.end([data][, encoding][, callback])
- 该方法会通知服务器,所有响应头和响应主体都已被发送,即服务器将其视为已完成。 每次响应都必须调用 response.end() 方法。
- 如果指定了 data,则相当于调用 response.write(data, encoding) 之后再调用 response.end(callback)。
- 如果指定了 callback,则当响应流结束时被调用。
再来看另外一个类IncomingMessage
,此时为客户端请求对象,同样的,它也是一个EventEmitter
,它包含了2个方法message.destroy()
,message.setTimeout()
,另外最常用的是它的属性:
- message.headers 查看客户端请求的头部信息
- message.method
- message.url
- message.statusCode
IncomingMessage
不仅在http作为服务端时作为实例传递,也在http作为客户端时实例化,不同的时候,参数略有不同,例如message.url
仅对作为服务器时有效,而message.statusCode
在作为客户端时有效,因为在作为服务器时表request
含义,在作为客户端时,表response
含义。下面我们再来看看,作为客户端时的情况。
http模块客户端的介绍
从最开始的属性与方法中我们可以看到有2种方法可以作为客户端时使用,并且与之相关的类为ClientRequest
和IncomingMessage
。
- http.request(options[, callback])
- http.get(options[, callback])
- 该方法是对request的封装,唯一区别是设置method为GET且自动调用了
req.end()
- 该方法不带有请求主体,即
request.write(chunk[, encoding][, callback])
,而quest当method为post时是需要带的
- 该方法是对request的封装,唯一区别是设置method为GET且自动调用了
我们先来看IncomingMessage
,此时作为响应体对象response
在回调中返回,通常情况下,我们添加这个回调函数用以接收response对象来处理响应结果,此时必须手动处理掉response,因为它是存在内存中的,有三种方法:
- response.read()
- response.on('data', chunk => { })
- response.resume()
此时我们可以查看IncomingMessage
中对于作为客户端response时的有效属性的含义。
ClientRequest
类,它的实例是在request
调用时创建。
// request 为ClientRequest实例
const request = http.request()
当使用post传递参数时,可以将参数以流的形式写入到请求主体中
request.write(formData)
request.end()
其他属性
- http.METHODS 返回解析器支持的 HTTP 方法的列表
- http.STATUS_CODES 返回标准的 HTTP 响应状态码的集合,以及各自的简短描述
{ '100': 'Continue', '101': 'Switching Protocols', '102': 'Processing', '200': 'OK' ... }
参考