-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttps-server.cjs
More file actions
115 lines (100 loc) · 3.46 KB
/
https-server.cjs
File metadata and controls
115 lines (100 loc) · 3.46 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
const https = require('https');
const fs = require('fs');
const path = require('path');
const url = require('url');
// 创建自签名证书(仅用于开发)
const selfsigned = require('selfsigned');
const attrs = [{ name: 'commonName', value: 'localhost' }];
const pems = selfsigned.generate(attrs, { days: 365 });
// MIME类型映射
const mimeTypes = {
'.html': 'text/html',
'.js': 'text/javascript',
'.css': 'text/css',
'.json': 'application/json',
'.png': 'image/png',
'.jpg': 'image/jpg',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.wav': 'audio/wav',
'.mp4': 'video/mp4',
'.woff': 'application/font-woff',
'.ttf': 'application/font-ttf',
'.eot': 'application/vnd.ms-fontobject',
'.otf': 'application/font-otf',
'.wasm': 'application/wasm'
};
const server = https.createServer({
key: pems.private,
cert: pems.cert
}, (req, res) => {
// 设置CORS头
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
res.setHeader('Pragma', 'no-cache');
res.setHeader('Expires', '0');
if (req.method === 'OPTIONS') {
res.writeHead(200);
res.end();
return;
}
let pathname = url.parse(req.url).pathname;
// 默认文件
if (pathname === '/') {
pathname = '/main.html';
}
const filePath = path.join(__dirname, pathname);
// 检查文件是否存在
fs.access(filePath, fs.constants.F_OK, (err) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/html' });
res.end('<h1>404 Not Found</h1>');
return;
}
// 获取文件扩展名
const ext = path.extname(filePath).toLowerCase();
const contentType = mimeTypes[ext] || 'application/octet-stream';
// 读取并发送文件
fs.readFile(filePath, (err, data) => {
if (err) {
res.writeHead(500, { 'Content-Type': 'text/html' });
res.end('<h1>500 Internal Server Error</h1>');
return;
}
res.writeHead(200, { 'Content-Type': contentType });
res.end(data);
});
});
});
const PORT = 8443;
server.listen(PORT, () => {
console.log('🚀 HTTPS开发服务器已启动!');
console.log('📍 访问地址:');
console.log(` https://localhost:${PORT}/main.html`);
console.log(` https://127.0.0.1:${PORT}/main.html`);
console.log('');
console.log('⚠️ 重要提示:');
console.log(' 1. 首次访问会显示安全警告,这是正常的');
console.log(' 2. 请点击"高级" → "继续访问localhost(不安全)"');
console.log(' 3. 确保允许摄像头访问权限');
console.log(' 4. 按 Ctrl+C 停止服务器');
console.log('');
});
server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(`❌ 端口 ${PORT} 已被占用,请尝试其他端口`);
} else {
console.error('❌ 服务器启动失败:', err);
}
process.exit(1);
});
// 优雅关闭
process.on('SIGINT', () => {
console.log('\n🛑 正在关闭服务器...');
server.close(() => {
console.log('✅ 服务器已关闭');
process.exit(0);
});
});