美文网首页
nodeJS静态服务器

nodeJS静态服务器

作者: ElvisYang1993 | 来源:发表于2018-03-17 01:07 被阅读0次

    引入依赖模块

    let config = require('./config');
    let chalk = require('chalk');//粉笔模块(命令行变色)
    let http = require('http');//http模块
    let fs = require('fs');//文件模块
    let zlib = require('zlib');
    let handlebars = require('handlebars');//模板引擎
    let url = require('url');//url模块解析请求url
    let mime = require('mime');//mime模块通过文件名称/路径拿到内容类型
    let path = require('path');
    let {promisify,inspect} = require('util');
    let stat = promisify(fs.stat);
    let readdir = promisify(fs.readdir);
    process.env.DEBUG = 'static:*';
    let debug = require('debug')('static:app');
    
    

    编译模板函数

    function list() {
        //编译模板,得到渲染方法,传入数据
        let tmpl = fs.readFileSync(path.resolve(__dirname,'src/template','list.html'),'utf8');
        return handlebars.compile(tmpl);//返回一个函数
    }
    

    此函数主要用于编译模板,返回一个文件list列表用于返回给客户端。

    start方法启动服务

    start(){
        //启动服务
        let server = http.createServer();
        server.on('request',this.request.bind(this));
        server.listen(this.config.port,()=>{
            let url = `${this.config.host}:${this.config.port}`;
            debug(`start at ${chalk.green(url)}`);
        })
    }
    

    this.config.port可以自己定义端口,debug用于在控制台打印信息。

    请求处理方法

    async request(req,res){
        //接收请求
        let { pathname } = url.parse(req.url);
        let filepath = path.join(this.config.root,pathname);
        try{
            let statObj = await stat(filepath);
            if(statObj.isDirectory()){//判断是否为目录
                //是目录的话使用handlebars模板引擎渲染目录
                let files = await readdir(filepath);//字符串数组
                files = files.map((file)=>{
                    return {
                        name:file,
                        url:path.join(pathname,file)
                    }
                });
                let html = this.list({
                    title:pathname,
                    files:files
                });
                res.setHeader('Content-Type','text/html');
                this.sendFile(req,res,html,statObj,'html');
            }else{
                this.sendFile(req,res,filepath,statObj,'');
            }
        }catch (e){
            debug(inspect(e));
            this.sendError(req,res)
        }
    }
    

    这个是主要处理逻辑,首先通过解析客户端的请求url,通过path模块来拿到文件路径,第一个参数是config中配置的静态文件根目录;然后来判断当前请求的是文件还是目录,这里使用一个try catch代码块来捕获异常,如果请求的是个目录的话,遍历这个目录下的所有文件并且将文件名和文件路径传给list编译模板,然后交给发送方法去处理。

    发送处理方法

    sendFile(req,res,filepath,statObj,type){
        //发送文件
        let expires = new Date(Date.now() + 60 * 1000);
        //缓存设置
        res.setHeader('Expires', expires.toUTCString());
        res.setHeader('Cache-Control', 'max-age=600');
        res.setHeader('Accept-Range', 'bytes');//断点续传
        if(type == 'html'){
            res.end(filepath);
        }else {
            res.setHeader('Content-Type',mime.getType(filepath));
            fs.createReadStream(filepath).pipe(res);
        }
    }
    

    发送方法里设置的缓存策略为强制缓存,并且在发送方法里调用zlibFn方法去看客户端请求是否使用压缩,并在最后将内容pipe到res里返回给客户端。

    zlib压缩方法

    zlibFn(req,res){
        let acceptEncoding = request.headers['accept-encoding'];//压缩
        if (!acceptEncoding) {
            acceptEncoding = '';
        }
        if (acceptEncoding.match(/\bdeflate\b/)) {
            res.setHeader('Content-Encoding','deflate');
            return zlib.createDeflate();
        } else if (acceptEncoding.match(/\bgzip\b/)) {
            res.setHeader('Content-Encoding','gzip');
            return zlib.createGzip();
        } else {
            return null;
        }
    }
    

    这里主要是通过请求头中的accept-encoding来判断是否压缩,以何种方式压缩,压缩后返回一个流对象。

    初写node静态服务器(简易版)全部代码请见Github

    相关文章

      网友评论

          本文标题:nodeJS静态服务器

          本文链接:https://www.haomeiwen.com/subject/busdqftx.html