文章
HTTP/2在本地开发测试时的多种解决方案
目录
1. 使用自签名证书(最常用)#
生成自签名证书#
# 生成私钥
openssl genrsa -out localhost.key 2048
# 生成证书签名请求
openssl req -new -key localhost.key -out localhost.csr \\
-subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
# 生成自签名证书(有效期365天)
openssl x509 -req -days 365 -in localhost.csr -signkey localhost.key -out localhost.crt
Node.js 开发服务器配置#
const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
key: fs.readFileSync('./localhost.key'),
cert: fs.readFileSync('./localhost.crt')
});
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('<h1>Hello HTTP/2 with self-signed cert!</h1>');
});
server.listen(8443, () => {
console.log('HTTP/2 server running on <https://localhost:8443>');
console.log('Note: Browser will show security warning for self-signed certificate');
});
2. 使用 mkcert(推荐)#
mkcert 可以生成浏览器信任的本地证书:
安装和使用#
# 安装 mkcert (Mac)
brew install mkcert
# 或 Linux
sudo apt install libnss3-tools
wget -O mkcert <https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64>
chmod +x mkcert
sudo mv mkcert /usr/local/bin/
# 初始化(安装本地CA)
mkcert -install
# 为项目生成证书
mkcert localhost 127.0.0.1 ::1
# 生成的文件:
# localhost+2.pem (证书)
# localhost+2-key.pem (私钥)
在代码中使用#
const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
key: fs.readFileSync('./localhost+2-key.pem'),
cert: fs.readFileSync('./localhost+2.pem')
});
server.listen(8443, () => {
console.log('HTTP/2 server running on <https://localhost:8443>');
console.log('This certificate is trusted by browsers!');
});
3. 开发工具内置支持#
Webpack Dev Server#
// webpack.config.js
module.exports = {
devServer: {
https: true, // 自动生成证书
http2: true
}
};
// 或使用自定义证书
module.exports = {
devServer: {
https: {
key: fs.readFileSync('./localhost.key'),
cert: fs.readFileSync('./localhost.crt')
},
http2: true
}
};
Create React App#
# 设置环境变量使用HTTPS
HTTPS=true npm start
# 或使用自定义证书
HTTPS=true SSL_CRT_FILE=localhost.crt SSL_KEY_FILE=localhost.key npm start
Vite#
// vite.config.js
import { defineConfig } from 'vite'
import fs from 'fs'
export default defineConfig({
server: {
https: {
key: fs.readFileSync('./localhost.key'),
cert: fs.readFileSync('./localhost.crt')
}
}
})
4. 浏览器特殊处理#
Chrome 本地开发豁免#
# 启动Chrome时禁用证书验证(仅开发环境!)
google-chrome --ignore-certificate-errors-spki-list --ignore-certificate-errors --ignore-ssl-errors --allow-running-insecure-content
访问自签名证书站点#
当访问使用自签名证书的 https://localhost 时:
- 浏览器显示"不安全连接"警告
- 点击"高级"
- 点击"继续前往localhost(不安全)"
- 或者直接键盘输入 ****
thisisunsafe(Chrome快捷方式)
5. Docker 开发环境#
Docker Compose 配置#
version: '3.8'
services:
app:
build: .
ports:
- "8443:8443"
volumes:
- ./certs:/app/certs # 挂载证书
environment:
- SSL_CERT_PATH=/app/certs/localhost.crt
- SSL_KEY_PATH=/app/certs/localhost.key
6. 实际开发工作流示例#
完整的开发环境设置#
# 1. 安装 mkcert 并生成证书
mkcert -install
mkcert localhost 127.0.0.1 ::1 myapp.test
# 2. 启动开发服务器
npm run dev
# 3. 访问 <https://localhost:3000> (浏览器自动信任)
Express + HTTP/2 开发配置#
const express = require('express');
const http2 = require('http2');
const fs = require('fs');
const spdy = require('spdy'); // 或者使用spdy包
const app = express();
app.get('/', (req, res) => {
res.send('Hello HTTP/2!');
});
// 开发环境:使用自签名证书
const options = {
key: fs.readFileSync('./localhost+2-key.pem'),
cert: fs.readFileSync('./localhost+2.pem'),
allowHTTP1: true // 允许HTTP/1.1回退
};
// 生产环境:使用真实证书
// const options = {
// key: fs.readFileSync('/etc/ssl/private/private.key'),
// cert: fs.readFileSync('/etc/ssl/certs/certificate.crt')
// };
spdy.createServer(options, app).listen(8443, () => {
console.log('HTTP/2 Express server running on <https://localhost:8443>');
});
7. 最佳实践总结#
开发环境证书管理#
# 推荐的项目结构
project/
├── certs/ # 证书目录(添加到.gitignore)
│ ├── localhost+2.pem
│ └── localhost+2-key.pem
├── src/
├── package.json
└── README.md
环境特定的配置#
// config/ssl.js
const fs = require('fs');
const path = require('path');
const isDevelopment = process.env.NODE_ENV === 'development';
const sslConfig = isDevelopment ? {
// 开发环境:自签名证书
key: fs.readFileSync(path.join(__dirname, '../certs/localhost+2-key.pem')),
cert: fs.readFileSync(path.join(__dirname, '../certs/localhost+2.pem'))
} : {
// 生产环境:真实证书
key: fs.readFileSync(process.env.SSL_KEY_PATH),
cert: fs.readFileSync(process.env.SSL_CERT_PATH)
};
module.exports = sslConfig;
8. 常见问题解决#
证书信任问题#
# 如果证书不被信任,重新安装mkcert的CA
mkcert -uninstall # 先卸载
mkcert -install # 重新安装
端口被占用#
# 查找占用端口的进程
lsof -i :8443
# 或者使用不同的端口
server.listen(3443, () => {
console.log('Server running on <https://localhost:3443>');
});
总结:对于本地HTTP/2开发,推荐使用 mkcert 生成浏览器信任的本地证书,这样既保证了开发体验,又能够完全测试HTTP/2的所有特性。这是目前最优雅的本地开发解决方案。