Node.js 模拟Apache服务器
1.知识必备
(1)当服务器响应不同文件类型时,需要设置响应报文头,让浏览器选择相应的编码解析数据。
常用对照表HTTP Mime-type:
https://tool.oschina.net/commons
思路:根据访问的路径来提取后缀名,再根据后缀名设置相应的 Content-Type
(2)请求路径不存在时设置返回的状态码
res.statusCode = 404
res.statusMessage = 'Not found'
(3)需要用到path模块和fs模块拼接路径即读取文件
2.模拟Apache服务器(一)
共封装了4个方法;
getFileType(url):根据url获取文件类型
setContentType(res,fileType):根据文件类型设置Mime-type
renderFile(res,url):根据路径读取相应的文件并返回给客户端
troubleShooting(res,url,fileType):错误处理函数
源码:
// 引入http模块
const http = require("http");
//引入fs模块
const fs = require('fs');
//引入path模块 (拼接路径)
const path = require('path');
// 创建一个服务器
var server = http.createServer((req,res)=>{
//获取文件类型
var fileType = getFileType(req.url)
if(!fileType) fileType = "html"
//设置ContentType
setContentType(res,fileType)
//读取文件并返回
renderFile(res,req.url)
});
// 监听接口,需运行此文件,浏览器才能正常访问 "127.0.0.1"
server.listen(80,"127.0.0.1",function(err){
if(err){
throw err;
}
console.log('Server running at http://127.0.0.1:80/');
});
//根据url获取后缀名
function getFileType(url){
//定义文件类型
var fileType = ""
//获取 "." 在url中的下标位置
var index = url.lastIndexOf('.')
if(index>=0){
// xxx.jpg => jpg
fileType = url.substring(index+1)
}
return fileType
}
//根据后缀名设置响应头
function setContentType(res,fileType){
var contrast = {
html:"text/html;charset=utf-8",
css:"text/css",
txt:"text/plain;charset=utf-8",
jpg:"image/jpeg",
png:"image/png",
jpeg:"image/jpeg",
svg:"text/xml",
gif:"image/gif",
mp3:"audio/mp3",
mp4:"video/mpeg4",
pdf:"application/pdf"
}
//设置默认的ContentType为text/html;charset=utf-8
var ContentType = "text/html;charset=utf-8"
//如果文件类型为空,则默认设置为html格式
if(!fileType) fileType = "html"
//匹配文件类型
Object.keys(contrast).forEach((key) => {
if(key === fileType){
ContentType = contrast[key]
//跳出遍历
return false
}
})
//设置响应头
res.setHeader("Content-Type",ContentType)
}
//封装读取文件的函数 (依赖path和fs模块)
function renderFile(res,url){
//如果访问根目录
if(url=='/'){
url = '/index.html';
}
//设置静态文件根目录
var root = "www"
//拼接路径
var filePath = path.join(__dirname,root,url)
//读取文件
fs.readFile(filePath,function(err,data){
if(err){
//处理异常
troubleShooting(res,url,fileType)
}else{
//返回文件内容
res.end(data)
}
})
}
//封装处理错误的函数
function troubleShooting(res,url,fileType){
console.log(url+"文件不存在")
//设置返回的状态码
res.statusCode = 404
res.statusMessage = 'Not found'
//根据文件类型返回不同的数据
if(fileType){
res.end("")
}else{
//返回404页面
res.end("页面不存在")
}
}
3.模拟Apache服务器(二)
(1)文件类型多种多样,每样都要手动设置Mime-Type费时费力,可以使用第三方模块来完成
这个模块就是 mime
安装mime模块
npm i mime
mime的作用就是根据url的后缀,返回对应的Content-Type。
语法:mime.getType(urlStr)
const mime = require("mime")
console.log(mime.getType("xxx.css")) // text/css
console.log(mime.getType("/")) // null
完整代码:
//引入http模块(用于创建http服务)
const http = require('http');
//引入path模块 (用于拼接路径)
const path = require('path');
//引入fs模块 (用于读取文件)
const fs = require('fs');
//引入mime模块(用于设置mime-type)
const mime = require('mime');
//创建http服务对象
var server = http.createServer((req,res)=>{
//根据url获取对应的mime-type
var contentType = mime.getType(req.url);
//设置Content-Type
res.setHeader('Content-Type',contentType);
//根据url读取对应的文件并返回给客户端
returnFile(req.url,res);
})
//根据url返回对应的文件
function returnFile(url,res){
//如果访问根目录就视为访问index.html
if(url=='/'){
url = '/index.html';
}
//设置静态资源目录
var root = "www"
//拼接路径
var targetPath = path.join(__dirname,root,url);
fs.readFile(targetPath,function(err,data){
if(err){
res.end('页面不存在');
}
res.end(data);
})
}
//开启服务,监听80端口
server.listen(80,"127.0.0.1",function(err){
if(err){
throw err;
}
console.log('Server running at http://127.0.0.1:80/');
})
4.总结
(1)搭建服务器需要的模块有:
- http:创建http服务
- path:拼接路径
- fs:读取文件
- mime:设置mime-type
(2)搭建服务器的步骤为:
- 引入相关模块
- 创建http服务对象,设置路由,监听用户访问的路径
- 根据url设置mime-type,保证客户端能正确解析数据
- 读取要返回的文件并响应给客户端
- 结束响应