node 内置模块之 http
网络服务http
http
可以说是最核心的模块,可以利用该模块几行代码就可以搞定一个迷你的 Web Server
简单例子
首先创建一个 Web 服务器和一个 http 客户端
- 服务器 server:接受来自客户端的请求,将客户端的请求地址返回给客户端
- 客户端 client:向服务器发起请求,将服务器返回的内容打印到控制台
const http = require('http')
// http server
const server = http.createServer((req,res) => {
const url = req.url
res.end(`访问地址是:${url}`)
});
server.listen(81, () => {
console.log('81端口被占用了')
});
// http client
const client = http.get('http://127.0.0.1:81',res=> {
res.pipe(process.stdout)
});
在上面这个简单的例子里,涉及了4个实例。大部分时候,serverReq、serverRes 才是主角。
- server:http.Server实例,用来提供服务,处理客户端的请求。
- client:http.ClientReques实例,用来向服务端发起请求。
- req/res:其实都是 http.IncomingMessage实例。req 用来获取客户端请求的相关信息,如request header;而res用来获取服务端返回的相关信息,比如 response header。
- serverRes:http.ServerResponse实例
关于 http.IncomingMessage、http.ServerResponse
http.ServerResponse:服务器端通过 http.ServerResponse 实例,来给请求方发送数据,包括响应头,响应主题等
http.IncomingMessage:在服务器端,获取请求发送方的信息,比如路径、方法、传递的数据;在客户端,获取服务器端发送来的信息,比如路径、方法、传递的数据等。
http res
一个 Web 服务程序,接收来自客户端的 http 请求后,向客户端返回正确的响应内容,这就是res
的主要职责。返回的内容包括:状态代码、响应头、响应主题
var http = require('http')
// 设置状态码、状态描述信息、响应主体
var server = http.createServer((req, res) => {
res.writeHead(200, 'ok', {
'Content-Type': 'text/plain'
});
res.end('hello')
});
server.listen(3000)
设置状态代码、描述信息
res.writeHead()、res.statusCode、res.statusMessage
例如设置状态代码为200,状态信息为 ok
res.writeHead(200,'ok')
// 或者
res.statusCode = 200
res.statusMessage = 'ok'
两者差异:
- res.writeHead() 可以提供额外的功能,例如设置响应头部
- 当响应头部发送出去后,res.statusCode、res.statusMessage 都会被设置成已发送出去的状态
设置响应头部
res.writeHeader()、res.setHeader()
例如将 Content-Type 设置为 text/plain
// 方法一
res.writeHead(200, 'ok', {
'Content-Type': 'text-plain'
});
// 方法二
res.setHeader('Content-Type', 'text-plain');
两者差异:
- res.writeHead() 不单单设置 header
- res.writeHeader() 和 res.setHeader() 都设置了同名 header时,res.writeHead() 会覆盖之前的设置
例如:下面的代码最终的 Content-Type 是 text/plain
const http = require('http');
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html')
res.writeHead(200, 'ok', {
'Content-Type': 'text/plain'
});
res.end('hello')
});
server.listen(3000)
而下面的例子则会报错:Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, 'ok', {
'Content-Type': 'text/plain'
});
res.setHeader('Content-Type', 'text/html')
res.end('hello')
});
server.listen(3000)
其他响应头部操作
增删改查比较简单:
// 增
res.setHeader('Content-Type', 'text/plain');
// 删
res.removeHeader('Content-Type');
// 改
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Type', 'text/html'); // 覆盖
// 查
res.getHeader('content-type');
其中 res.getHeader(name) 中的 name 使用的是小写,返回值没有进行特殊处理,设置的是什么就返回什么:
// 设置的是大写,返回大写
res.setHeader('Content-Type', 'TEXT/HTML');
console.log( res.getHeader('content-type') ); // TEXT/HTML
// 设置的是小写,返回小写
res.setHeader('Content-Type', 'text/plain');
console.log( res.getHeader('content-type') ); // text/plain
设置响应主体
res.write()、res.end()
res.write() 的 api 较多,看看官方文档吧
res.write(chunk,[,encoding][,callback])
- chunk:响应主体的内容,string、buffer,当内容为 string 时,encoding 用来指定编码格式,默认是 utf8
- encoding:编码格式,默认 utf8
- callback:回调函数
注意事项:
-
如果要使用 res.write 最后必须要有res.end,否则浏览器处于请求状态
-
多条语句输出使用的是 res.write,并且也结合HTML标签进行使用
res.end()
res.end()相比较res.write()要简单许多,用处是告诉 node,header 和 body 都穿过去了,此次响应就结束吧
所以多次调用 res.end() 时,只有第一次的调用有效,其他都无效
超时处理
res.setTimeout()
网络服务 http req
获取 HTTP 版本、请求方法、请求地址、请求头部
// HTTP 报文
GET /hello HTTP/1.1
Host: 127.0.0.1:3000
Connection: keep-alive
Cache-Control: no-cache
······
// 获取
const http = require('http')
const server = http.createServer((req,res) => {
console.log('1. 客户端请求url:' + req.url )
console.log('1. http 版本:' + req.httpVersion )
console.log('1. http 请求方法:' + req.method )
console.log('1. http 请求头部:' + JSON.stringify(req.headers) )
res.end('ok')
})
server.listen(3000)
// 控制台打印信息:
1、客户端请求url:/hello
2、http版本:1.1
3、http请求方法:GET
4、http headers:{"host":"127.0.0.1:3000","connection":"keep-alive","cache-control":"no-cache","user-age