Revel 不支持原生二级域名路由,需通过 Nginx 透传 Host 头并在中间件中解析子域名注入上下文;Nginx 必须配置 proxy_set_header Host $host;,且多个二级域名应共用同一 Revel 实例并分 server 块精确匹配。

Revel 应用本身不支持二级域名路由分组
Revel 框架没有类似 Laravel 的 Route::domain() 机制,它的路由系统基于请求路径(GET /item),不原生解析或匹配 Host 头。所有二级域名的请求,只要最终被代理到 Revel 进程,都会进入同一套路由表——除非你在中间件或控制器里手动判断 $request->Host 并分支处理。
Nginx 必须透传 Host 头,否则 Revel 看不到真实域名
Revel 依赖 $_SERVER['HTTP_HOST'](即 PHP 中的 $_SERVER['HTTP_HOST'])获取原始请求域名。如果 Nginx 配置漏掉 proxy_set_header Host $host;,Revel 收到的会是 127.0.0.1:8089 或空值,导致域名逻辑失效。
- 必须在
location /块中显式设置:proxy_set_header Host $host; - 同时补全:
proxy_set_header X-Real-IP $remote_addr;和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - 若启用 HTTPS,还要加:
proxy_set_header X-Forwarded-Proto $scheme;,否则revel.Session().Get()可能因协议误判而丢 session
用中间件实现二级域名上下文隔离
推荐在 Revel 的 app/init.go 中注册一个全局中间件,提前解析 Host 并注入请求上下文,避免每个 controller 重复写判断逻辑。
- 检查
c.Request.Host是否匹配预设模式,如^([a-z0-9]+)\.example\.com$ - 提取子域名(如
api、admin)并存入c.Params.Set("subdomain", sub) - 后续 controller 可直接读:
c.Params.Get("subdomain"),用于切换数据库连接、加载租户配置等 - 不要在
Filter阶段做重定向(如 301 跳转),这会破坏 RESTful 语义,且干扰 API 客户端
宝塔/Nginx 站点配置必须指向同一 Revel 实例
多个二级域名(如 api.example.com、admin.example.com)不能各自建独立站点再反向代理——那样会触发两次代理,Header 易丢失。正确做法是:只建一个主站点(如 example.com),然后在 Nginx 配置中用多个 server 块分别监听各二级域名,并统一代理到 http://127.0.0.1:8089。
- 每个
server块的server_name必须精确匹配,例如:server_name api.example.com; - 避免用泛域名
*.example.com,除非你确认所有子域名都走同一套逻辑;否则攻击者可注册hacker.example.com绕过校验 - 本地开发时,
/etc/hosts必须为每个测试子域名添加条目:127.0.0.1 api.example.com admin.example.com



















