github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/client/web/resolver.go (about) 1 package web 2 3 import ( 4 "errors" 5 "math/rand" 6 "net/http" 7 "regexp" 8 "strings" 9 10 "github.com/tickoalcantara12/micro/v3/service/api/resolver" 11 res "github.com/tickoalcantara12/micro/v3/service/api/resolver" 12 "github.com/tickoalcantara12/micro/v3/service/router" 13 ) 14 15 var re = regexp.MustCompile("^[a-zA-Z0-9]+([a-zA-Z0-9-]*[a-zA-Z0-9]*)?$") 16 17 type WebResolver struct { 18 // Options 19 Options resolver.Options 20 // selector to choose from a pool of nodes 21 // Selector selector.Selector 22 // router to lookup routes 23 Router router.Router 24 } 25 26 func (r *WebResolver) String() string { 27 return "web/resolver" 28 } 29 30 // Resolve replaces the values of Host, Path, Scheme to calla backend service 31 // It accounts for subdomains for service names based on namespace 32 func (r *WebResolver) Resolve(req *http.Request, opts ...res.ResolveOption) (*res.Endpoint, error) { 33 // parse the options 34 options := resolver.NewResolveOptions(opts...) 35 36 parts := strings.Split(req.URL.Path, "/") 37 if len(parts) < 2 { 38 return nil, errors.New("unknown service") 39 } 40 41 if !re.MatchString(parts[1]) { 42 return nil, res.ErrInvalidPath 43 } 44 45 // lookup the routes for the service 46 query := []router.LookupOption{ 47 router.LookupNetwork(options.Domain), 48 } 49 50 routes, err := r.Router.Lookup(parts[1], query...) 51 if err == router.ErrRouteNotFound { 52 return nil, res.ErrNotFound 53 } else if err != nil { 54 return nil, err 55 } else if len(routes) == 0 { 56 return nil, res.ErrNotFound 57 } 58 59 // select a random route to use 60 // todo: update to use selector once go-micro has updated the interface 61 // route, err := r.Selector.Select(routes...) 62 // if err != nil { 63 // return nil, err 64 // } 65 route := routes[rand.Intn(len(routes))] 66 67 // we're done 68 return &res.Endpoint{ 69 Name: parts[1], 70 Method: req.Method, 71 Host: route.Address, 72 Path: "/" + strings.Join(parts[2:], "/"), 73 Domain: options.Domain, 74 }, nil 75 }