예제 #1
0
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)
	}
}
예제 #2
0
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)
}
예제 #3
0
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))
			}
		}
	}
}
예제 #4
0
// 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()
}