You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Gorilla Mux实现多子域名托管?

问题描述

需要使用Gorilla Mux实现多子域名托管,支持以下访问路径:

  • https://www.izzat.com/api/v1/user/get
  • https://auth.izzat.com/api/v2/get

以下是我编写的Go代码和Nginx配置,需排查问题并完成适配:

现有Go代码
func NewHttpServer(l logger.Logger, c config.Config, routes []Routes, r *mux.Router) *Http {

        r.Use(middleware.LoggingMiddleware(l))

        v1 := r.Host("www.izzat.com").PathPrefix("/api/v1/").Subrouter()

        for _, route := range routes {
                route.InitRoutes(v1)
        }

        v2 := r.Host("auth.izzat.com").PathPrefix("/api/v2/").Subrouter()
        v2.HandleFunc("/get", Test)

        spa1 := SpaHandler{
                IndexPath:  "index.html",
                StaticPath: "web/dist",
        }

        r.PathPrefix("/").Handler(spa1)

        return &Http{
                logger: l,
                config: c,
        }
}
现有Nginx配置
server {
        listen 80;
        listen [::]:80;
        server_name *.izzat.com;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        #ssl_certificate /etc/letsencrypt/live/izzat.com/fullchain.pem;
        #ssl_certificate_key /etc/letsencrypt/live/izzat.com/privkey.pem;
        #include /etc/letsencrypt/options-ssl-nginx.conf;
        #ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        location / {
                proxy_pass http://myserver.hostname:3000;
        }
}
问题分析与修正方案

1. Nginx核心问题:未传递Host头

默认Nginx反向代理不会将客户端的Host头转发给后端服务,导致Gorilla Mux的Host()子域名匹配规则完全失效。必须在Nginx的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;
proxy_set_header X-Forwarded-Proto $scheme;

2. Gorilla Mux路由优化

  • 路径前缀处理:原代码中PathPrefix("/api/v1/")末尾的斜杠可能导致路径拼接问题,建议改为PathPrefix("/api/v1"),内部注册路由时直接写/user/get即可,避免重复前缀。
  • SPA路由隔离:原代码中r.PathPrefix("/").Handler(spa1)会匹配所有未被捕获的请求,包括子域名的非API路径,建议给SPA路由指定专属Host,避免干扰子域名路由。

修正后的代码示例

修正后的Go代码

func NewHttpServer(l logger.Logger, c config.Config, routes []Routes, r *mux.Router) *Http {
    r.Use(middleware.LoggingMiddleware(l))

    // www子域名的v1 API路由
    v1 := r.Host("www.izzat.com").PathPrefix("/api/v1").Subrouter()
    for _, route := range routes {
        route.InitRoutes(v1)
    }
    // 若routes未注册目标路径,可手动添加示例:
    // v1.HandleFunc("/user/get", UserGetHandler)

    // auth子域名的v2 API路由
    v2 := r.Host("auth.izzat.com").PathPrefix("/api/v2").Subrouter()
    v2.HandleFunc("/get", Test)

    // 仅根域名匹配SPA路由
    spaRouter := r.Host("izzat.com").PathPrefix("/").Subrouter()
    spa1 := SpaHandler{
        IndexPath:  "index.html",
        StaticPath: "web/dist",
    }
    spaRouter.PathPrefix("/").Handler(spa1)

    return &Http{
        logger: l,
        config: c,
    }
}

修正后的Nginx配置

server {
    listen 80;
    listen [::]:80;
    server_name *.izzat.com;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    # 启用HTTPS时取消以下注释
    #ssl_certificate /etc/letsencrypt/live/izzat.com/fullchain.pem;
    #ssl_certificate_key /etc/letsencrypt/live/izzat.com/privkey.pem;
    #include /etc/letsencrypt/options-ssl-nginx.conf;
    #ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://myserver.hostname:3000;
        # 关键:传递Host头及客户端信息
        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;
    }
}

验证步骤

  1. 重启Nginx和Go服务
  2. 测试https://www.izzat.com/api/v1/user/get是否路由到对应处理函数
  3. 测试https://auth.izzat.com/api/v2/get是否触发Test函数
  4. 测试根域名https://izzat.com是否正常加载SPA页面

内容的提问来源于stack exchange,提问作者нαzιq ιzzαт

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 03:11:52