// Proxy is a reverse proxy used by the micro web and api func Proxy(ns string, ws bool) http.Handler { return &proxy{ Namespace: ns, Selector: cache.NewSelector( selector.Registry((*cmd.DefaultOptions().Registry)), ), re: regexp.MustCompile("^[a-zA-Z0-9]+$"), ws: ws, } }
func (s *srv) proxy() http.Handler { sel := cache.NewSelector( selector.Registry((*cmd.DefaultOptions().Registry)), ) director := func(r *http.Request) { kill := func() { r.URL.Host = "" r.URL.Path = "" r.URL.Scheme = "" r.Host = "" r.RequestURI = "" } parts := strings.Split(r.URL.Path, "/") if len(parts) < 2 { kill() return } if !re.MatchString(parts[1]) { kill() return } next, err := sel.Select(Namespace + "." + parts[1]) if err != nil { kill() return } s, err := next() if err != nil { kill() return } r.Header.Set(BasePathHeader, "/"+parts[1]) r.URL.Host = fmt.Sprintf("%s:%d", s.Address, s.Port) r.URL.Path = "/" + strings.Join(parts[2:], "/") r.URL.Scheme = "http" r.Host = r.URL.Host } return &proxy{ Default: &httputil.ReverseProxy{Director: director}, Director: director, } }
func TestWatcher(t *testing.T) { r := setupRegistry() c := cache.NewSelector(selector.Registry(r)) // wait for watcher to get setup time.Sleep(time.Millisecond) // check that service is blank if _, err := c.Select("foo.service"); err != registry.ErrNotFound { log.Fatal("expected registry.ErrNotFound") } // setup svc svc1 := ®istry.Service{Name: "foo.service", Version: "1"} register(r, "pod-1", svc1) time.Sleep(time.Millisecond) var wg sync.WaitGroup wg.Add(3) c.Select("foo.service", selector.WithFilter(func(svcs []*registry.Service) []*registry.Service { defer wg.Done() if !hasServices(svcs, []*registry.Service{svc1}) { t.Fatal("expected services to match") } return nil })) // setup svc svc2 := ®istry.Service{Name: "foo.service", Version: "1"} register(r, "pod-2", svc2) time.Sleep(time.Millisecond) c.Select("foo.service", selector.WithFilter(func(svcs []*registry.Service) []*registry.Service { defer wg.Done() if !hasNodes(svcs[0].Nodes, []*registry.Node{svc1.Nodes[0], svc2.Nodes[0]}) { t.Fatal("expected to have same nodes") } return nil })) // deregister os.Setenv("HOSTNAME", "pod-1") r.Deregister(svc1) time.Sleep(time.Millisecond) c.Select("foo.service", selector.WithFilter(func(svcs []*registry.Service) []*registry.Service { defer wg.Done() if !hasServices(svcs, []*registry.Service{svc2}) { t.Fatal("expected services to match") } return nil })) // remove pods teardownRegistry() time.Sleep(time.Millisecond) if _, err := c.Select("foo.service"); err != registry.ErrNotFound { log.Fatal("expected registry.ErrNotFound") } out := make(chan bool) go func() { wg.Wait() close(out) }() select { case <-out: return case <-time.After(time.Second): t.Fatal("expected c.Select() to be called 3 times") } }
func NewSelector(opts ...selector.Option) selector.Selector { return cache.NewSelector(opts...) }