Revel 不支持直接启用 HTTPS,必须由 Nginx 等前置服务器终止 SSL 并以 HTTP 转发请求;因其基于 net/http 缺乏证书续期、SNI、安全头过滤等生产能力,且硬编码证书风险高,官方明确禁止暴露 HTTPS 端口。

Revel 本身不处理 HTTPS,必须由前置 Web 服务器(如 Nginx)终止 SSL,再以 HTTP 转发到 Revel 进程 —— 这是唯一安全、可行的生产方案。
为什么不能直接在 Revel 中启用 HTTPS
Revel 的 revel run 启动的 HTTP 服务基于 Go 标准库 net/http,虽支持 TLS,但缺乏生产级能力:无法自动续期证书、不支持 SNI 多域名、无连接限速/请求头过滤/静态资源缓存,且私钥和证书硬编码在配置中风险极高。官方文档与所有部署指南均明确禁止直接暴露 Revel 的 HTTPS 端口。
Nginx 配置 HTTPS 并正确透传协议头
关键不是“让 Revel 支持 HTTPS”,而是确保 Nginx 把原始请求的真实协议信息准确传递过去,否则 revel.Session().Get()、revel.BaseURL() 等会误判为 HTTP,导致 Cookie 丢失或重定向错乱。
- 必须设置
X-Forwarded-Proto:Nginx 的server块中需包含proxy_set_header X-Forwarded-Proto $scheme;($scheme在 HTTPS server 块中自动为https) - 禁用
proxy_redirect:Revel 自动根据X-Forwarded-Proto重写Location响应头,手动配置proxy_redirect会覆盖它,引发 302 跳转到http://地址 - 不要只配 443 端口:建议同时保留 80 端口并强制跳转,例如
return 301 https://$host$request_uri;
示例片段(/etc/nginx/sites-available/myapp):
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/certs/fullchain.pem;
ssl_certificate_key /etc/ssl/certs/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8089;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # ← 必须有
}
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}Revel 应用内需适配的两个地方
即使 Nginx 配置正确,Revel 默认行为仍可能出问题,需主动检查:
-
app.conf中确认app.mode = prod:开发模式下部分中间件逻辑不同,且revel run会忽略某些 header 透传 - Session Cookie 安全标记:若使用默认 Cookie 存储,确保
session.cookie.secure = true(仅在 HTTPS 下发送),否则浏览器拒绝发送 Cookie - 模板中生成 URL 时,避免硬编码
http://:改用{{baseurl}}或revel.BaseURL(),它依赖X-Forwarded-Proto返回正确协议
Let's Encrypt 自动续期与 Revel 无关
证书更新(如 certbot renew)只影响 Nginx 配置文件中的 ssl_certificate 和 ssl_certificate_key 路径指向的文件内容。Revel 进程完全无感知,无需重启或 reload —— 只要 Nginx 在 reload 配置后重新读取了新证书即可。常见错误是续期后忘记 nginx -s reload,导致 Nginx 仍在用旧证书。
最易被忽略的是:X-Forwarded-Proto 没传或传错值,会让整个会话和重定向逻辑静默失效,现象是登录后跳回 HTTP 页面或反复要求登录 —— 此时看 Nginx access log 里的 $scheme 和 Revel 日志里的实际接收 header 就能快速定位。


















