-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstatic_server.js
More file actions
130 lines (110 loc) · 3.6 KB
/
static_server.js
File metadata and controls
130 lines (110 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// 引入所需的核心模块
const http = require('http');
const url = require('url');
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');
// 定义默认端口号
const PORT = 3000;
// 定义静态资源目录
const STATIC_DIR = path.join(__dirname, 'public');
// 创建HTTP服务器
const server = http.createServer((req, res) => {
// 解析请求的URL
const parsedUrl = url.parse(req.url);
// 获取请求的路径
let pathname = parsedUrl.pathname;
// 如果请求的是根路径,返回index.html
if (pathname === '/') {
pathname = '/index.html';
}
// 构建文件的绝对路径
const filePath = path.join(STATIC_DIR, pathname);
// 读取文件并发送响应
fs.stat(filePath, (err, stats) => {
if (err) {
// 如果文件不存在,返回404错误
console.error(`File not found: ${filePath}`);
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
return;
}
// 如果是目录,则返回403错误
if (stats.isDirectory()) {
res.writeHead(403, { 'Content-Type': 'text/plain' });
res.end('403 Forbidden');
return;
}
// 根据文件扩展名设置Content-Type
const ext = path.extname(filePath).toLowerCase();
const contentType = getContentType(ext);
// 检查客户端是否支持gzip压缩
const acceptEncoding = req.headers['accept-encoding'] || '';
const useGzip = acceptEncoding.includes('gzip');
// 设置基本的响应头
const headers = {
'Content-Type': contentType,
'Cache-Control': 'max-age=86400' // 一天的缓存时间
};
// 创建文件读取流
const fileStream = fs.createReadStream(filePath);
// 处理文件流错误
fileStream.on('error', (error) => {
console.error(`Error reading file: ${error}`);
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('500 Internal Server Error');
});
// 如果支持gzip且文件适合压缩
if (useGzip && shouldCompress(ext)) {
// 添加gzip压缩头
headers['Content-Encoding'] = 'gzip';
res.writeHead(200, headers);
// 创建gzip压缩流并管道连接
const gzipStream = zlib.createGzip();
fileStream.pipe(gzipStream).pipe(res);
} else {
// 不使用压缩
res.writeHead(200, headers);
fileStream.pipe(res);
}
});
});
// 启动服务器
server.listen(PORT, () => {
console.log(`静态资源服务器运行在 http://localhost:${PORT}/`);
console.log(`静态资源目录: ${STATIC_DIR}`);
});
// 根据文件扩展名获取Content-Type
function getContentType(ext) {
const contentTypes = {
'.html': 'text/html; charset=utf-8',
'.css': 'text/css; charset=utf-8',
'.js': 'application/javascript; charset=utf-8',
'.json': 'application/json; charset=utf-8',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.ico': 'image/x-icon',
'.txt': 'text/plain; charset=utf-8',
'.pdf': 'application/pdf',
'.woff': 'font/woff',
'.woff2': 'font/woff2',
'.ttf': 'font/ttf',
'.eot': 'application/vnd.ms-fontobject',
'.otf': 'font/otf',
'.mp4': 'video/mp4',
'.webm': 'video/webm',
'.mp3': 'audio/mpeg',
'.wav': 'audio/wav'
};
return contentTypes[ext] || 'application/octet-stream';
}
// 判断文件类型是否应该被压缩
function shouldCompress(ext) {
const compressibleTypes = [
'.html', '.css', '.js', '.json', '.txt', '.svg'
];
return compressibleTypes.includes(ext);
}