每天学点node系列-http
任何可以使用JavaScript来编写的应用,最终会由JavaScript编写。--Atwood's Law
http模块概览
http模块主要用于创建http server服务,并且
- 支持更多特性
- 不缓冲请求和响应
- 能够流式传输数据
借助http模块,可以几行代码就搞定一个超迷你的web server:
var http=require("http")
http.createServer(function(req, res){
res.writeHead(200,{
"content-type":"text/plain"
})
res.write("hello nodejs")
res.end()
}).listen(3000)
http服务器
像上面一样使用的createServer方法返回了一个http.Server对象,这其实是一个创建http服务的捷径,如果我们用以下代码来实现的话,也将一样可行
var http = require("http")
var server = new http.Server()
server.on("request", function(req, res){
res.writeHead(200, {
"content-type":"text/plain"
})
res.write("hello nodejs")
res.end()
})
server.listen(3000)
以上代码是通过直接创建一个http.Server对象,然后为其添加request事件监听,其实也就说createServer方法其实本质上也是为http.Server对象添加了一个request事件监听。
http.Server的事件
http.Server继承自 net.Server,http.Server提供的事件如下:
- request:当客户端请求到来时,该事件被触发,提供两个参数req和res,表示请求和响应信息,是最常用的事件
- connection:当TCP连接建立时,该事件被触发,提供一个参数socket,是net.Socket的实例
- close:当服务器关闭时,触发事件(注意不是在用户断开连接时)
正如上面我们所看到的request事件是最常用的,而参数req和res分别是http.IncomingMessage和http.ServerResponse的实例,那么我们来看看这两个类
http.IncomingMessage
**在server端:获取请求发送方的信息,比如请求方法、路径、传递的数据等。 **
在client端:获取 server 端发送过来的信息,比如请求方法、路径、传递的数据等。
http.IncomingMessage实例 有三个属性需要注意:method、statusCode、statusMessage。
- method:只在 server 端的实例有(也就是 serverReq.method)
- statusCode/statusMessage:只在 client 端 的实例有(也就是 clientRes.method)
并且其提供了3个事件,如下
- data:当请求体数据到来时,该事件被触发,该事件提供一个参数chunk,表示接受的数据,如果该事件没有被监听,则请求体会被抛弃,该事件可能会被调用多次(这与nodejs是异步的有关系)
- end:当请求体数据传输完毕时,该事件会被触发,此后不会再有数据
- close:用户当前请求结束时,该事件被触发,不同于end,如果用户强制终止了传输,也是用close
http.ServerResponse
http.ServerResponse 的作用很明确,服务端通过http.ServerResponse 实例,来个请求方发送数据。包括发送响应表头,发送响应主体等。它决定了用户最终看到的内容,一般也由http.Server的request事件发送,并作为第二个参数传递,它有三个重要的成员函数,用于返回响应头、响应内容以及结束请求
- res.writeHead(statusCode,[heasers]):向请求的客户端发送响应头,该函数在一个请求中最多调用一次,如果不调用,则会自动生成一个响应头
- res.write(data,[encoding]):想请求的客户端发送相应内容,data是一个buffer或者字符串,如果data是字符串,则需要制定编码方式,默认为utf-8,在res.end调用之前可以多次调用
- res.end([data],[encoding]):结束响应,告知客户端所有发送已经结束,当所有要返回的内容发送完毕时,该函数必需被调用一次,两个可选参数与res.write()相同。如果不调用这个函数,客户端将用于处于等待状态。
http客户端
http模块提供了两个函数http.request和http.get,功能是作为客户端向http服务器发起请求。
var http = require('http')
// http server
var server = http.createServer(function(req, res){
var url = req.url
res.end( '您访问的地址是:' + url )
})
server.listen(3000)
// http client
var client = http.get('http://127.0.0.1:3000', function(res){
res.setEncoding("utf-8")
res.on("data",function(chunk){
console.log(chunk.toString())
})
console.log(res.statusCode);
})
client.on("error",function(err){
console.log(err.message)
})
client.end()
http.ClientRequest
此对象由 http.request()
内部创建并返回。 它表示正在进行的请求,且其请求头已进入队列。 请求头仍然可以使用 setHeader(name, value)
、getHeader(name)
或 removeHeader(name)
改变。 实际的请求头将与第一个数据块一起发送,或者当调用 request.end()
时发送。
要获得响应,则为请求对象添加 'response'
事件监听器。 当接收到响应头时,将、则会从请求对象触发 'response' 事件。 'response' 事件执行时有一个参数,该参数是 http.IncomingMessage 的实例。
在 'response'
事件期间,可以添加监听器到响应对象,比如监听 'data'
事件。
如果没有添加 'response' 事件处理函数,则响应将被完全丢弃。 如果添加了 'response' 事件处理函数,则必须消费完响应对象中的数据,每当有 'readable' 事件时调用 response.read()、或添加 'data' 事件处理函数、或通过调用 .resume() 方法。 在消费完数据之前,不会触发 'end' 事件。 此外,在读取数据之前,它将占用内存,最终可能导致进程内存不足的错误。
Node.js 不检查 Content-Length 和已传输的主体的长度是否相等。
请求继承自流,且额外实现以下内容:
- 'abort': 当请求被客户端中止时触发。 此事件仅在第一次调用 abort() 时触发。
- 'timeout':当底层套接字因不活动而超时时触发。 这只会通知套接字已空闲。 必须手动中止请求。
- ...