Revel框架本身不支持HTTPS,必须由Nginx反向代理终结TLS;其底层基于Go net/http,无RunTLS接口,生产环境须监听127.0.0.1:8089并由Nginx在443端口处理SSL终止、透传X-Forwarded-Proto,且cookie.secure = true。

Revel 框架本身不支持 HTTPS,强行在代码里加 ListenAndServeTLS 或改 app.conf 配置 https.port 是无效的——它底层用的是 Go 标准库 net/http.Server,而该类型没有运行时 TLS 启动能力,也没有证书热加载、SNI、自动续期等生产必需功能。你真正要配的不是 Revel,是 Nginx。
为什么不能直接让 Revel 监听 443 端口
常见错误现象:revel run -p 443 报 permission denied;或加了 -https 参数后启动失败、日志无响应、健康检查超时。
根本原因:Revel 的 http.Server 不提供 RunTLS 接口,官方也明确禁止暴露 HTTPS 端口。所有试图“绕过 Nginx 自己上 TLS”的做法,都会破坏进程管理、日志统一、反向代理头透传,且无法满足微信小程序等平台对完整证书链、TLS 1.2+、域名精确匹配的硬性要求。
必须接受的事实:Revel 只能跑 HTTP,HTTPS 终止必须由前置服务器(如 Nginx)完成。
Nginx SSL 证书配置的三个硬性条件
缺一不可,否则客户端(尤其是 iOS/Android/微信)会报 SSL routines:tls_process_server_certificate:certificate verify failed 或静默失败。
-
ssl_certificate必须指向 PEM 文件,且内容顺序为:**域名证书 + 中间 CA 证书**(例如 Let’s Encrypt 的fullchain.pem),只放cert.pem会导致握手失败 -
ssl_certificate_key必须是未加密私钥(生成时用了-nodes),带密码的私钥会让 Nginx 启动时报SSL_CTX_use_PrivateKey_file(...) failed (SSL: error:0906406D:PEM routines:PEM_def_callback:problems getting password) - 私钥文件权限必须为
0600(Linux/macOS),Nginx worker 进程以非 root 用户(如www-data)运行,若权限是0644,读取会静默失败或报Permission denied
验证命令:
openssl x509 -in /path/to/fullchain.pem -text -noout | head -20
应看到两个 Certificate 块;
openssl rsa -in /path/to/key.pem -check -noout
应输出 RSA key ok。
HTTP 强制跳转 HTTPS 和协议头透传
Revel 应用收不到原始请求是 HTTP 还是 HTTPS,全靠 Nginx 透传 X-Forwarded-Proto。漏掉这步,revel.Session().Get()、revel.BaseURL()、重定向地址都会变成 http://,Cookie 也会因 secure=true 被浏览器丢弃。
Nginx 配置关键项:
- 在
server { listen 443 ssl; ... }块中,必须有:proxy_set_header X-Forwarded-Proto $scheme; - 在
server { listen 80; ... }块中,强制跳转:return 301 https://$host$request_uri; - 禁用
proxy_redirect:Revel 会根据X-Forwarded-Proto自动重写Location响应头,手动设proxy_redirect会覆盖它,导致跳转到http://地址
同时,app.conf 中必须设置:cookie.secure = true,否则即使 HTTPS 到达,Cookie 仍可能被非安全连接发送。
Revel 启动时监听地址和端口的正确写法
开发模式默认监听 0.0.0.0:9000,但生产环境必须绑定本地回环,否则 Nginx 反代形同虚设,且存在严重暴露风险。
启动命令示例:
revel run -a myapp -p 8089 -addr 127.0.0.1 -c /path/to/conf
对应 conf/app.conf 中需显式声明:
http.port = 8089http.addr = "127.0.0.1"
别信“先跑起来再加固”的说法——如果 netstat -tuln | grep :8089 显示监听的是 *:8089,说明已对外暴露,立刻停掉并修正。
最易被忽略的一点:证书链完整性不是“有证书就行”,而是“客户端是否信任你”。微信小程序后台校验时,会严格走信任链验证,中间证书缺失、域名不完全匹配、TLS 版本低于 1.2,任一条件不满足,都只会显示“request:fail net::ERR_CERT_COMMON_NAME_INVALID”之类模糊错误,排查时得从 OpenSSL 层级逐段验证,而不是反复改 Revel 配置。











