Node之http模块
const http = require('http');
const request = http.request('http://duyi.ke.qq.com/', {
method: 'GET'
}, resp => {
console.log('状态码', resp.statusCode);
console.log('响应头', resp.headers);
let result = ''
resp.on('data', chunk => {
// console.log(chunk.toString('utf-8'))
result += chunk.toString('utf-8');
})
resp.on('end', chunk => {
console.log(result)
})
})
request.end()//必须给一个结束的消息
http 模块是在 net 模块之上建立的,它省去了 socket 的管理编写和消息格式的编写。有两个 API ,一个是创建客户端,一个是创建服务器。客户端一个是响应自己搭建的服务器,一个是响应远程服务器。
http.request() 里面可以传入三个参数。第一个是路径,第二个是配置对象,第三个是回调函数,拿到响应后的结果。
类似上面的例子,创建一个客户端。我们可以直接解析响应结果,不用像之前再进行手动书写。必须写响应体,使用 write 和 end 。可以只写 end ,但不能不写。如果不写会导致服务器一直等待,不会返回响应结果。
响应体一定要从流里面读取,因为有可能流的内容很多,如果直接读取可能导致无法读取,所以采用流的方式读取。
const url = require('url')
function handleReq(req){
console.log('有请求来了')
const urlObj = url.parse(req.url)
console.log('请求路径', urlObj)
console.log('请求方法', req.method)
console.log('请求头', req.headers)
let body = ''
req.on('data', chunk => {
body += chunk.toString('utf-8')
})
req.on('end', () => {
console.log('请求体', body)
})
}
const server = http.createServer((req, res) => {
handleReq(req)
res.setHeader('a', '1')
res.setHeader('b', '2')
res.statusCode = 404
res.write('你好!')
res.end()
})
server.listen(8000)
server.on('listening', () => {
console.log('服务器启动成功')
})
同样,可以创建一个服务器。可以传配置对象和回调函数。回调函数表示请求已经到达。使用 createServer 来创建,req 表示收到的请求,res 表示返回的响应结果。同样,请求体使用流来进行传输。
不管是客户端还是服务器,收到消息的都是 IncomingMessage 对象,客户端从响应拿到消息,服务器从请求拿到消息。客户端发出请求是 ClientRequest 对象,服务器响应结果是 ServerResponse 对象。注意一定要分清。
const path = require('path')
const URL = require('url')
const fs = require('fs')
//搭建静态资源服务器,就是把请求路径和文件路径对应
/**
* 获取文件信息
* @param {*} filename
*/
async function getStat(filename) {
try{
return await fs.promises.stat(filename)
}
catch{
return null;
}
}
/**
* 处理文件内容
* @param {*} url
*/
async function getFileContent(url) {
const urlObj = URL.parse(url)
let filename = path.resolve(__dirname,'myfiles/public', urlObj.pathname.substring(1))
let stat = await getStat(filename)
if(!stat){
return null
}else if(stat.isDirectory()){
filename = path.resolve(__dirname,'myfiles/public', urlObj.pathname.substring(1), 'index.html')
stat = await getStat(filename)
if(!stat){
return null
}else{
return await fs.promises.readFile(filename)
}
}else{
return await fs.promises.readFile(filename)
}
}
async function handler(req, res) {
const info = await getFileContent(req.url)
if(info){
res.write(info)
}else{
res.statusCode = 404
res.write('Resource is not exist')
}
res.end()
}
const server = http.createServer(handler)
server.listen(8000)
server.on('listening', () => {
console.log('服务器启动成功')
})
我们要搭建一个静态资源服务器,需要根据文件路径来得到请求路径。先创建一个处理函数,设置监听端口。然后通过 getFileContent 请求路径得到本地文件内容,通过 url 地址进行解析,解析成对象。再通过一个函数 getStat 进行文件是否存在的判断。如果文件存在返回状态,否则返回 null 。
在 getFileContent 函数里得到状态以后,如果文件不存在返回 null ,接着判断是否为目录,如果是目录接着进行判断,找到文件路径呢就返回,不是目录则返回文件路径。
在 handler 函数里拿到文件内容以后,如果有内容就响应内容,没有内容就返回 404 错误。这样就实现了本地服务器的功能。
更改静态资源是不需要重启服务器的。注意实现过程中的异步函数,promise 一定返回 true ,忘了加 await 就会导致一直返回为 true 。