大家好,
我正在开发一个项目,我需要使用路径设置多个子域。我尝试了两个子域的代码,但在我的情况下,它将是100个子域。我为此尝试了以下代码:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type Subdomains map[string]http.Handler
func (subdomains Subdomains) ServeHTTP(w http.ResponseWriter, r *http.Request) {
domainParts := strings.Split(r.Host, ".")
if mux := subdomains[domainParts[0]]; mux != nil {
mux.ServeHTTP(w, r)
} else {
http.Error(w, "Not found", 404)
}
}
func main() {
r := gin.Default()
r2 := gin.Default()
hs := make(Subdomains)
hs["admin"] = r
hs["analytics"] = r2
r.GET("/ping", adminHandlerOne)
r2.GET("/ping", adminHandlerOne)
http.ListenAndServe(":9090", hs)
}
func adminHandlerOne(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
}
但我认为这不好。有人知道这样做的正确方法吗?
答案 0 :(得分:0)
您可以使用*httputil.ReverseProxy
。这是我将基于主机名重新路由到子域的方式,而Gin中没有任何中间件。
router.GET("/:username", func(c *gin.Context) {
uri, ok := c.Get("location")
if !ok {
c.JSON(500, gin.H{
"reason": "Location unknown",
})
}
hostname := "awesome.io"
if uri.(*url.URL).Host == hostname {
// Want to send client to "https://auth.awesome.io/:username"
s := fmt.Sprintf("https://auth.%s/%s", domain, c.Param("username"))
uri, err := url.Parse(s)
if err != nil {
c.JSON(500, gin.H{
"reason": "Subdomain is wrong",
})
}
rp := new(httputil.ReverseProxy)
// Modify request's URL to point to the new uri
rp.Director = func(req *http.Request) {
req.URL = uri
}
rp.ServeHTTP(c.Writer, c.Request)
}
})
答案 1 :(得分:-1)
你有几个选择(写一个路由器,写包装,尝试弯曲杜松子酒你的意志),但由于默认的ServeMux支持这个,你可能真的不需要杜松子酒,我&#39 ; d使用标准路由器。首先看一下DefaultServeMux的来源,以了解路由器的简单性 - 路由器只是处理程序路径的映射。
默认ServeMux实际上做了你想要的(允许匹配主机和路径),所以我建议先尝试一下。注册您的模式:
mux := http.NewServeMux()
mux.HandleFunc("/", handlerRoot)
mux.HandleFunc("analytics.example.com/", handlerOne)
mux.HandleFunc("admin.example.com/", handlerTwo)
err := http.ListenAndServe(":9090", mux)
if err != nil {
panic(err)
}
写一些处理程序(很明显你可能用编码器而不是直接编写json,这只是一个例子):
func handlerOne(w http.ResponseWriter, r *http.Request) {
j := fmt.Sprintf(`{"one":"%s"}`, r.Host)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(j))
}
如果您在本地主机上测试此内容,则可能需要编辑/ etc / hosts文件以确保使用正确的主机名命中服务器。
将它们放在一起,您可以使用以下内容进行测试:
https://play.golang.org/p/ut-GT_s3Gf
请注意,如果您愿意,这些子域可以是动态的(提到100加上让我认为它们可能是),并且您可以在运行时在处理程序中自定义行为而不是使用单独的处理程序,它取决于域的行为有多么不同。