func TestIntegSingle(t *testing.T) { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {}) srvr := httptest.NewServer(mux) u, err := url.Parse(srvr.URL) if err != nil { t.Fatal(err) } urls := []*url.URL{u} rule := &porter.Rule{"127.0.0.1", urls} p, err := porter.New([]*porter.Rule{rule}) if err != nil { t.Fatal(err) } pMux := http.NewServeMux() pMux.Handle("/", p) pSrvr := httptest.NewServer(pMux) res, err := http.Get(pSrvr.URL + "/") if err != nil { t.Fatal(err) } defer res.Body.Close() want := http.StatusOK got := res.StatusCode if want != got { t.Fatalf("want %d, got %d", want, got) } }
func Example() { // don't normally discard errors u0, _ := url.Parse("www.dest0.localhost") u1, _ := url.Parse("www.dest1.localhost") u2, _ := url.Parse("www.dest2.localhost") u3, _ := url.Parse("www.dest3.localhost") urls0 := []*url.URL{u0, u1} urls1 := []*url.URL{u2, u3} rule0 := &porter.Rule{"www.src0.localhost", urls0} rule1 := &porter.Rule{"www.src1andfallback.localhost", urls1} p, err := porter.New([]*porter.Rule{rule0, rule1}) if err != nil { fmt.Println(err) } http.ListenAndServe(":8383", p) }
func TestIntegMulti(t *testing.T) { rules := []*porter.Rule{} for n := 0; n < 3; n++ { urls := []*url.URL{} for i := 0; i < 3; i++ { mux := http.NewServeMux() mux.HandleFunc("/", func(x int) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "%d", x) } }(n*10+i)) srvr := httptest.NewServer(mux) u, err := url.Parse(srvr.URL) if err != nil { t.Fatal(err) } urls = append(urls, u) } rule := &porter.Rule{ "www." + strconv.Itoa(n) + ".localhost", urls, } rules = append(rules, rule) } p, err := porter.New(rules) if err != nil { t.Fatal(err) } pMux := http.NewServeMux() pMux.Handle("/", p) pSrvr := httptest.NewServer(pMux) for n := 0; n < 3; n++ { rets := []string{} for i := 0; i < 12; i++ { cl := &http.Client{} req, err := http.NewRequest("GET", pSrvr.URL+"/", nil) if err != nil { t.Fatal(err) } req.Host = "www." + strconv.Itoa(n) + ".localhost" res, err := cl.Do(req) if err != nil { t.Fatal(err) } defer res.Body.Close() b, err := ioutil.ReadAll(res.Body) if err != nil { t.Fatal(err) } rets = append(rets, string(b)) } for i := 0; i < 3; i++ { if !containsVal(rets, strconv.Itoa(n*10+i)) { t.Errorf("could not find val %q", strconv.Itoa(n*10+i)) } } } }
// Run iterates over servers map and runs each server. func (cl *Cluster) Run() { cl.mu.Lock() startupWG := &sync.WaitGroup{} startupWG.Add(len(cl.nodes)) cl.runWG.Add(len(cl.nodes)) liveNodes := []*Node{} for _, v := range cl.nodes { if !v.deathrow.IsZero() { startupWG.Done() cl.runWG.Done() continue } liveNodes = append(liveNodes, v) go func(n *Node) { n.nodeWG.Wait() sc := n.StopChan() ec := make(chan error) go func() { l, err := net.Listen("tcp", n.addrOrig) if err != nil { panic(err) } n.Addr = portFromString(l.Addr().String()) u, err := url.Parse("http://127.0.0.1" + n.Addr) if err != nil { panic(err) } n.rule = &porter.Rule{ Host: n.ID, URLs: []*url.URL{u}, } n.nodeWG.Add(1) n.muPower.Lock() n.power = true n.muPower.Unlock() n.SetKeepAlivesEnabled(false) startupWG.Done() if err := n.Serve(l); err != nil { ec <- err } }() select { case <-sc: case err := <-ec: if !strings.Contains(err.Error(), "closed network") { n.ErrorLog.Println("error:", err) } } n.nodeWG.Done() n.muPower.Lock() n.power = false n.muPower.Unlock() cl.runWG.Done() }(v) } cl.nodes = liveNodes startupWG.Wait() cl.rProxs = make(map[string]*revProx) for _, v := range cl.nodes { if v.RevProxAddr == "" { continue } if _, ok := cl.rProxs[v.RevProxAddr]; !ok { cl.rProxs[v.RevProxAddr] = &revProx{ rules: make([]*porter.Rule, 0), } } cl.rProxs[v.RevProxAddr].rules = append(cl.rProxs[v.RevProxAddr].rules, v.rule) } for k, v := range cl.rProxs { p, err := porter.New(v.rules) if err != nil { panic(err) } m := http.NewServeMux() m.Handle("/", p) cl.rProxs[k].Server = &graceful.Server{ Timeout: time.Second * 12, ListenLimit: 0, NoSignalHandling: true, Server: &http.Server{ Addr: k, Handler: cl.reco(cl.PreMW(m)), }, } go func(rp *revProx) { sc := rp.StopChan() ec := make(chan error) rp.SetKeepAlivesEnabled(false) if err := rp.ListenAndServe(); err != nil { ec <- err } select { case <-sc: case err := <-ec: if !strings.Contains(err.Error(), "closed network") { // TODO fmt.Println("error:", err) } } }(cl.rProxs[k]) } cl.stopWG.Add(1) cl.mu.Unlock() }