github.com/annwntech/go-micro/v2@v2.9.5/api/resolver/subdomain/subdomain.go (about) 1 package subdomain 2 3 import ( 4 "net" 5 "net/http" 6 "strings" 7 8 "github.com/annwntech/go-micro/v2/api/resolver" 9 "github.com/annwntech/go-micro/v2/logger" 10 "golang.org/x/net/publicsuffix" 11 ) 12 13 func NewResolver(parent resolver.Resolver, opts ...resolver.Option) resolver.Resolver { 14 options := resolver.NewOptions(opts...) 15 return &Resolver{options, parent} 16 } 17 18 type Resolver struct { 19 opts resolver.Options 20 resolver.Resolver 21 } 22 23 func (r *Resolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) { 24 if dom := r.Domain(req); len(dom) > 0 { 25 opts = append(opts, resolver.Domain(dom)) 26 } 27 28 return r.Resolver.Resolve(req, opts...) 29 } 30 31 func (r *Resolver) Domain(req *http.Request) string { 32 // determine the host, e.g. foobar.m3o.app 33 host := req.URL.Hostname() 34 if len(host) == 0 { 35 if h, _, err := net.SplitHostPort(req.Host); err == nil { 36 host = h // host does contain a port 37 } else if strings.Contains(err.Error(), "missing port in address") { 38 host = req.Host // host does not contain a port 39 } 40 } 41 42 // check for an ip address 43 if net.ParseIP(host) != nil { 44 return "" 45 } 46 47 // check for dev enviroment 48 if host == "localhost" || host == "127.0.0.1" { 49 return "" 50 } 51 52 // extract the top level domain plus one (e.g. 'myapp.com') 53 domain, err := publicsuffix.EffectiveTLDPlusOne(host) 54 if err != nil { 55 logger.Debugf("Unable to extract domain from %v", host) 56 return "" 57 } 58 59 // there was no subdomain 60 if host == domain { 61 return "" 62 } 63 64 // remove the domain from the host, leaving the subdomain, e.g. "staging.foo.myapp.com" => "staging.foo" 65 subdomain := strings.TrimSuffix(host, "."+domain) 66 67 // ignore the API subdomain 68 if subdomain == "api" { 69 return "" 70 } 71 72 // return the reversed subdomain as the namespace, e.g. "staging.foo" => "foo-staging" 73 comps := strings.Split(subdomain, ".") 74 for i := len(comps)/2 - 1; i >= 0; i-- { 75 opp := len(comps) - 1 - i 76 comps[i], comps[opp] = comps[opp], comps[i] 77 } 78 return strings.Join(comps, ".") 79 } 80 81 func (r *Resolver) String() string { 82 return "subdomain" 83 }