首页 > Web开发 > 详细

Node.js 模拟Apache服务器

时间:2019-10-11 15:54:19      阅读:75      评论:0      收藏:0      [点我收藏+]

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)req和res对象
创建http服务对象时,需要传入一个函数,用于处理用户的请求(判断请求地址和返回数据等)。这个传入的函数自带两个参数:req和res

req包含用户请求的信息,常用的有:

  • req.url:请求路径 例如www.xxx.com/yyy => /yyy
  • req.method:客户端请求使用的方法(get,post...)
  • req.headers:返回所有的请求报文头,例如User-Agent/HostCookie等

res用来向客户端响应数据,常用的有:

  • res.writeHead():向请求发送响应头,只能在消息上调用一次,即使代码没有写,系统默认也会调用它。
res.writeHead(200, { 'Content-Type': 'text/plain' })
  • res.setHeader():设置响应头,例如
res.setHeader('Content-Type', 'text/html')
  • res.write():该方法发送一块响应主体。 可以多次调用该方法以提供连续的响应主体片段
res.write('hello wolrd')
res.write('good life')
  • res.end():此方法向服务器发出信号,表明已发送所有响应头和主体,该服务器应该视为此消息已完成。
    注意:必须在每个响应上调用此 response.end() 方法,不然浏览器会一直转圈圈等待服务器的相应
res.end()
  • 设置http响应状态码
    res.statusCode:响应状态码
    res.statusMessage:响应状态码对应的消息
response.statusCode = 404;
response.statusMessage = 'Not found';

1XX:Infomational(信息性状态码)接收的请求正在处理
2XX:Success(成功状态码)请求正常处理完毕
3XX:Redirection(重定向状态码)需要进行附加操作以完成请求
4XX:Client Error(客户端错误状态码)服务器无法处理请求
5XX:Server Error(服务器错误状态码)服务器处理请求出错

Node.js 模拟Apache服务器

原文:https://www.cnblogs.com/OrochiZ-/p/11653527.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!