当前位置: 首页 > 后端技术 > Node.js

搭建一个Node.js静态服务器

时间:2023-04-03 16:46:38 Node.js

对于Node.js初学者来说,搭建一个静态服务器可以加深对TCP/IP的理解。在学习过程中,我参考了Node大师蒲凌。本文主要讲述构建中的思路,加深对TCP/IP的理解。服务器知识。主要实现以下功能:执行命令读取指定目录下的静态文件MIME类型支持缓存支持/控制支持gzip压缩只能访问指定目录,不能访问指定目录的上层目录,保证安全访问目录可以自动找到下面的index.html文件范围支持,断点续传项目初始化###项目目录指定命令行文件创建命令行#!/usr/bin/envnodeletyargs=require('yargs');letServer=require('../src/app.js');letargv=yargs.option('d',{别名:'root',demand:'false',type:'string',default:process.cwd(),description:'静态文件根目录'}).option('o',{别名:'host',demand:'false',default:'localhost',type:'string',description:'请配置监听主机'}).option('p',{alias:'port',demand:'false',type:'number',default:9090,description:'请配置端口号'}).usage('static-server1[options]').example('static-server1-d/-p9890-olocalhost','监听客户端请求onport9090ofthismachine').help('h').argv;//argv={d,root,o,host,p,port}letserver=newServer(argv);server.start();//static-server1//命令行中的命令指向npm目录下的bat文件,bat文件也指向当前目录下的www文件staticservercoreclassCreateserverinstancestart(){//创建服务实例letserver=http.createServer()server.on('request',this.request.bind(this))server.listen(this.config.port,()=>{leturl=`http://${this.config.host}:${this.config.port}`debug(`serverstartedat${chalk.green(url)}`)})}创建服务器的响应asyncrequest(req,res){let{pathname}=url.parse(req.url)if(pathname==='/favicon.ico'){returnthis.sendError('notfound',req,res)}让filePath=path.join(this.config.root,pathname)try{letstatObj=awaitstat(filePath)if(statObj.isDirectory()){letfiles=awaitreaddir(filePath)files=files.map(file=>({name:file,url:path.join(pathname,file)}))lethtml=this.list({title:pathname,files})res.setHeader('Content-Type','text/html')res.end(html)}else{this.sendFile(req,res,filePath,statObj)}}catch(e){debug(inspect(e))//inspect将对象转换为字符this.sendError(e,req,res)}}文件类型的处理sendFile(req,res,filePath,statObj){//如果使用缓存,直接返回if(this.handleCache(req,res,filePath,statObj))returnres.setHeader('Content-Type',mime.getType(filePath)+';charset=utf-8')letencoding=this.getEncoding(req,res)letrs=this.getStream(req,res,filePath,statObj)if(encoding){rs.pipe(encoding).pipe(res)}else{rs.pipe(res)}-范围支持,断点恢复getStream(req,res,filePath,statObj){letstart=0;让结束=statObj。size-1letrange=req.headers['range']if(range){res.setHeader('Accept-Range','bytes')res.statusCode=206//返回全部内容的一部分letresult=范围。match(/bytes=(\d*)-(\d*)/)如果(结果){s挞=isNaN(结果[1])?开始:parseInt(result[1])end=isNaN(result[2])?end:parseInt(result[2])}}returnfs.createReadStream(filePath,{start,end})}处理缓存handleCache(req,res,filePath,statObj){letifModifiedSince=req.headers['if-modified-since']letisNoneMatch=req.headers['is-none-match']res.setHeader('Cache-Control','private,max-age=30')res.setHeader('Expires',newDate(Date.now()+30*1000).toGMTString())letetag=statObj.sizeletlastModified=statObj.ctime.toGMTString()res.setHeader('ETag',etag)res.setHeader('Last-Modified',lastModified)if(isNoneMatch&&isNoneMatch!=etag){returnfalse}if(ifModifiedSince&&ifModifiedSince!=lastModified){returnfalse}if(isNoneMatch||ifModifiedSince){res.writeHead(304)res.end()returntrue}else{returnfalse}}错误处理sendError(err,req,res){res.statusCode=500res.end(`${err.toString()}`)}压缩处理getEncoding(req,res){letacceptEncoding=req.headers['accept-encoding']if(/\bgzip\b/.test(acceptEncoding)){res.setHeader('Content-Encoding','gzip')返回zlib.createGzip()}elseif(/\bdeflate\b/.test(acceptEncoding)){res.setHeader('Content-Encoding','deflate')returnzlib.createDeflate()}else{returnnull}}项目运行代码已经发布在npm1中。在当前目录下执行npmlink,将当前的statc-server1命令添加到命令中。你可以检查一下。可以看到当目录已经生成的时候,可以在这里找到已经使用过的vue-cli命令。2.执行~setDEBUG=static*~3,执行命令~static-server1~,默认9090,目前可以访问http:localhost:9090