static-server-function
Version:
179 lines (167 loc) • 7.94 kB
JavaScript
//1.引入http模块
const http = require('http');
//引入url模块
const urlTool = require('url')
//引入 path模块
const path = require('path');
//引入fs模块
const fs = require('fs')
//引入ejs(模块化工具)
const ejs = require('ejs');
//引入 mimes 对象(响应头)
const mimes = require('./mimes/mimes')
//引入zlib模块 (压缩)
const zlib = require('zlib')
//引入 etag 工具
const etag = require('etag')
//引入配置文件对象
const config = require('./config/config')
//引入 open.js
const open = require('./libs/open')
class H51227{
constructor(options){
Object.assign(config, options);
console.log(config);
}
run(){
//2.创建服务
const server = http.createServer((request,response) =>{
//获取请求的路径
let url = urlTool.parse(request.url).pathname;
//拼接文件的路径
// resolve方法第二个参数如果是一个绝对路径,则返回这个绝对路径
// let filePath =path.resolve(config.root + url)
let filePath = config.root + url;
//检测路径对应资源的类型
fs.stat(filePath,(err,stats)=> {
if(err){
response.statusCode = 404;
response.end('<h1>404 Not Found</h1>')
return;
}
//检测是否为文件夹
if(stats.isDirectory()){
//读取文件夹中的内容
fs.readdir(filePath,(err,data)=>{
if(err){
response.statusCode = 500;
response.end('<h1>500 Internal Error</h1>')
return;
}
//设置一下响应头
response.setHeader('content-type','text/html;charset/utf-8');
let templateFilePath = path.resolve(__dirname,'views/directory.html')
ejs.renderFile(templateFilePath,{data:data,url:url},(err,data)=>{
if (err){
response.statusCode = 500;
response.end('<h1>500 Internal Error</h1>')
return ;
}
response.end(data)
})
})
}else{
//判断是否开启协商缓存
if(config.cache.xieCache) {
//检测客户端请求的 if-none-match if-modified-since
let requestEtag = request.headers['if-none-match']
let requestLastModified = request.headers['if-modified-since']
//重新计算当前文件的 etag 值
let currentFileEtag = etag(stats);
let currentFileModifiedTime = stats.mtime.toUTCString()
// //判断
if (requestEtag === currentFileEtag || requestLastModified === currentFileModifiedTime) {
//响应304
response.statusCode = 304;
response.end()
return;
}
}
//如果是文件的话
//获取文件的后缀 url /index.html
const suffix = url.split('.').pop();
if(mimes[suffix] === undefined){
//text/plain也是一种类型 浏览器会原文输出内容
response.setHeader('content-type','text/plain;charset=utf-8');
}else{
response.setHeader('content-type',mimes[suffix]);
}
//设置强制缓存 判断
if(config.cache.qiangCache){
response.setHeader('cache-control','max-age='+config.cache.cacheTime)
}
// response.setHeader('cache-control','max-age=300')
//设置协商缓存 etag
let etagValue = etag(stats);
response.setHeader('Etag',etagValue);
response.setHeader('last-modified',stats.mtime.toUTCString())
// 读取文件内容
fs.readFile(filePath,(err,data)=>{
if(err){
response.statusCode = 500;
response.end('<h1>Interval server Error</h1>')
return;
}
//判断支持的压缩方式
let encoding = request.headers['accept-encoding'];//undefined
//判断如果没有指定 encoding
if(encoding === undefined){
response.end(data) ;
return ;
}
// 判读encoding中是否有gzip
if (encoding.indexOf('gzip') !== -1) {
//设置响应头
response.setHeader('content-encoding', 'gzip');
//对响应头的数据进行压缩
zlib.gzip(data,(err,result)=>{
if(err){
//如果出错
response.statusCode = 500;
response.end('<h1>Interval server Error</h1>')
return;
}
response.end(result)
})
}
//判读encoding中是否有 deflate br
else if(encoding.indexOf('deflate')!==-1){
//设置响应头
response.setHeader('context-encoding','deflate')
//对响应头的数据进行压缩
zlib.deflate(data,(err,result)=>{
if(err){
response.statusCode = 500;
response.end('<h1>Interval server Error</h1>')
return;
}
response.end(result)
})
}
//判读encoding中是否有 br
else if(encoding.indexOf('br')!==-1){
//设置响应头
response.setHeader('context-encoding','br')
//对响应头的数据进行压缩
zlib.brotliCompress(data,(err,result)=>{
if(err){
response.statusCode = 500;
response.end('<h1>Interval server Error</h1>')
return;
}
response.end(result)
})
}
//传内容
})
}
})
})
//3.启动服务,监听端口
server.listen(config.port,()=>{
console.log(`服务已经启动,端口${config.port}监听中`)
open(`http://127.0.0.1:${config.port}`)
})
}
}
module.exports = H51227;