func (s *ServerSuite) TestBackendHTTPS(c *C) { e := httptest.NewUnstartedServer( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("hi https")) })) e.StartTLS() defer e.Close() b := MakeBatch(Batch{ Addr: "localhost:41000", Route: `Path("/")`, URL: e.URL, }) c.Assert(s.mux.UpsertHost(b.H), IsNil) c.Assert(s.mux.UpsertServer(b.BK, b.S), IsNil) c.Assert(s.mux.UpsertFrontend(b.F), IsNil) c.Assert(s.mux.UpsertListener(b.L), IsNil) c.Assert(s.mux.Start(), IsNil) re, _, err := testutils.Get(b.FrontendURL("/")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, 500) // failed because of bad cert b.B.Settings = engine.HTTPBackendSettings{TLS: &engine.TLSSettings{InsecureSkipVerify: true}} c.Assert(s.mux.UpsertBackend(b.B), IsNil) re, body, err := testutils.Get(b.FrontendURL("/")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, 200) c.Assert(string(body), Equals, "hi https") }
// If configMapper returns empty rates, then the default rate is applied. func (s *LimiterSuite) TestExtractorEmpty(c *C) { // Given extractor := func(*http.Request) (*RateSet, error) { return NewRateSet(), nil } rates := NewRateSet() rates.Add(time.Second, 1, 1) handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello")) }) l, err := New(handler, headerLimit, rates, Clock(s.clock), ExtractRates(RateExtractorFunc(extractor))) c.Assert(err, IsNil) srv := httptest.NewServer(l) defer srv.Close() // When/Then: The default rate is applied, which 1 req/second re, _, err := testutils.Get(srv.URL, testutils.Header("Source", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) re, _, err = testutils.Get(srv.URL, testutils.Header("Source", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, 429) s.clock.Sleep(time.Second) re, _, err = testutils.Get(srv.URL, testutils.Header("Source", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) }
func (s *ServerSuite) TestListenerScopeUpdate(c *C) { e := testutils.NewResponder("Hi, I'm endpoint") defer e.Close() c.Assert(s.mux.Start(), IsNil) b := MakeBatch(Batch{Addr: "localhost:41000", Route: `Path("/")`, URL: e.URL}) c.Assert(s.mux.UpsertServer(b.BK, b.S), IsNil) c.Assert(s.mux.UpsertFrontend(b.F), IsNil) c.Assert(s.mux.UpsertListener(b.L), IsNil) re, body, err := testutils.Get(b.FrontendURL("/"), testutils.Host("otherhost")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) c.Assert(string(body), Equals, "Hi, I'm endpoint") b.L.Scope = `Host("localhost")` c.Assert(s.mux.UpsertListener(b.L), IsNil) re, body, err = testutils.Get(b.FrontendURL("/"), testutils.Host("localhost")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) c.Assert(string(body), Equals, "Hi, I'm endpoint") re, _, err = testutils.Get(b.FrontendURL("/"), testutils.Host("otherhost")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusNotFound) }
// We've hit the limit and were able to proceed on the next time run func (s *LimiterSuite) TestOptions(c *C) { handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello")) }) rates := NewRateSet() rates.Add(time.Second, 1, 1) errHandler := utils.ErrorHandlerFunc(func(w http.ResponseWriter, req *http.Request, err error) { w.WriteHeader(http.StatusTeapot) w.Write([]byte(http.StatusText(http.StatusTeapot))) }) buf := &bytes.Buffer{} log := utils.NewFileLogger(buf, utils.INFO) l, err := New(handler, headerLimit, rates, ErrorHandler(errHandler), Logger(log), Clock(s.clock)) c.Assert(err, IsNil) srv := httptest.NewServer(l) defer srv.Close() re, _, err := testutils.Get(srv.URL, testutils.Header("Source", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) re, _, err = testutils.Get(srv.URL, testutils.Header("Source", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusTeapot) c.Assert(len(buf.String()), Not(Equals), 0) }
// Make sure rates from different ips are controlled separatedly func (s *LimiterSuite) TestIsolation(c *C) { handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello")) }) rates := NewRateSet() rates.Add(time.Second, 1, 1) l, err := New(handler, headerLimit, rates, Clock(s.clock)) c.Assert(err, IsNil) srv := httptest.NewServer(l) defer srv.Close() re, _, err := testutils.Get(srv.URL, testutils.Header("Source", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) // Next request from the same source hits rate limit re, _, err = testutils.Get(srv.URL, testutils.Header("Source", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, 429) // The request from other source can proceed re, _, err = testutils.Get(srv.URL, testutils.Header("Source", "b")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) }
// Test scenario when increaing the weight on good endpoints made it worse func (s *RBSuite) TestRebalancerCascading(c *C) { a, b, d := testutils.NewResponder("a"), testutils.NewResponder("b"), testutils.NewResponder("d") defer a.Close() defer b.Close() defer d.Close() fwd, err := forward.New() c.Assert(err, IsNil) lb, err := New(fwd) c.Assert(err, IsNil) newMeter := func() (Meter, error) { return &testMeter{}, nil } rb, err := NewRebalancer(lb, RebalancerMeter(newMeter), RebalancerClock(s.clock), RebalancerLogger(s.log)) c.Assert(err, IsNil) rb.UpsertServer(testutils.ParseURI(a.URL)) rb.UpsertServer(testutils.ParseURI(b.URL)) rb.UpsertServer(testutils.ParseURI(d.URL)) rb.servers[0].meter.(*testMeter).rating = 0.3 proxy := httptest.NewServer(rb) defer proxy.Close() for i := 0; i < 6; i += 1 { testutils.Get(proxy.URL) testutils.Get(proxy.URL) s.clock.CurrentTime = s.clock.CurrentTime.Add(rb.backoffDuration + time.Second) } // We have increased the load, and the situation became worse as the other servers started failing c.Assert(rb.servers[0].curWeight, Equals, 1) c.Assert(rb.servers[1].curWeight, Equals, FSMMaxWeight) c.Assert(rb.servers[2].curWeight, Equals, FSMMaxWeight) // server a is now recovering, the weights should go back to the original state rb.servers[0].meter.(*testMeter).rating = 0.3 rb.servers[1].meter.(*testMeter).rating = 0.2 rb.servers[2].meter.(*testMeter).rating = 0.2 for i := 0; i < 6; i += 1 { testutils.Get(proxy.URL) testutils.Get(proxy.URL) s.clock.CurrentTime = s.clock.CurrentTime.Add(rb.backoffDuration + time.Second) } // the algo reverted it back c.Assert(rb.servers[0].curWeight, Equals, 1) c.Assert(rb.servers[1].curWeight, Equals, 1) c.Assert(rb.servers[2].curWeight, Equals, 1) }
// Test scenario when one server goes down after what it recovers func (s *RBSuite) TestRebalancerRecovery(c *C) { a, b := testutils.NewResponder("a"), testutils.NewResponder("b") defer a.Close() defer b.Close() fwd, err := forward.New() c.Assert(err, IsNil) lb, err := New(fwd) c.Assert(err, IsNil) newMeter := func() (Meter, error) { return &testMeter{}, nil } rb, err := NewRebalancer(lb, RebalancerMeter(newMeter), RebalancerClock(s.clock), RebalancerLogger(s.log)) c.Assert(err, IsNil) rb.UpsertServer(testutils.ParseURI(a.URL)) rb.UpsertServer(testutils.ParseURI(b.URL)) rb.servers[0].meter.(*testMeter).rating = 0.3 proxy := httptest.NewServer(rb) defer proxy.Close() for i := 0; i < 6; i += 1 { testutils.Get(proxy.URL) testutils.Get(proxy.URL) s.clock.CurrentTime = s.clock.CurrentTime.Add(rb.backoffDuration + time.Second) } c.Assert(rb.servers[0].curWeight, Equals, 1) c.Assert(rb.servers[1].curWeight, Equals, FSMMaxWeight) c.Assert(lb.servers[0].weight, Equals, 1) c.Assert(lb.servers[1].weight, Equals, FSMMaxWeight) // server a is now recovering, the weights should go back to the original state rb.servers[0].meter.(*testMeter).rating = 0 for i := 0; i < 6; i += 1 { testutils.Get(proxy.URL) testutils.Get(proxy.URL) s.clock.CurrentTime = s.clock.CurrentTime.Add(rb.backoffDuration + time.Second) } c.Assert(rb.servers[0].curWeight, Equals, 1) c.Assert(rb.servers[1].curWeight, Equals, 1) // Make sure we have applied the weights to the inner load balancer c.Assert(lb.servers[0].weight, Equals, 1) c.Assert(lb.servers[1].weight, Equals, 1) }
func (s *VESuite) TestHTTPSListenerCRUD(c *C) { called := false server := testutils.NewHandler(func(w http.ResponseWriter, r *http.Request) { called = true w.Write([]byte("Hi, I'm fine, thanks!")) }) defer server.Close() b, srv, url := "bk1", "srv1", server.URL _, err := s.client.Set(s.path("backends", b, "backend"), `{"Type": "http"}`, 0) c.Assert(err, IsNil) _, err = s.client.Set(s.path("backends", b, "servers", srv), fmt.Sprintf(`{"URL": "%s"}`, url), 0) c.Assert(err, IsNil) // Add frontend fId := "fr1" _, err = s.client.Set(s.path("frontends", fId, "frontend"), `{"Type": "http", "BackendId": "bk1", "Route": "Path(\"/path\")"}`, 0) c.Assert(err, IsNil) keyPair := NewTestKeyPair() bytes, err := secret.SealKeyPairToJSON(s.box, keyPair) c.Assert(err, IsNil) sealed := base64.StdEncoding.EncodeToString(bytes) host := "localhost" _, err = s.client.Set(s.path("hosts", host, "host"), fmt.Sprintf(`{"Name": "localhost", "Settings": {"KeyPair": "%v"}}`, sealed), 0) c.Assert(err, IsNil) // Add HTTPS listener l2 := "ls2" listener, err := engine.NewListener(l2, "https", "tcp", "localhost:32000", "", nil) c.Assert(err, IsNil) bytes, err = json.Marshal(listener) c.Assert(err, IsNil) s.client.Set(s.path("listeners", l2), string(bytes), 0) time.Sleep(time.Second) _, _, err = testutils.Get(fmt.Sprintf("%s%s", "https://localhost:32000", "/path")) c.Assert(err, IsNil) c.Assert(called, Equals, true) _, err = s.client.Delete(s.path("listeners", l2), true) c.Assert(err, IsNil) time.Sleep(time.Second) _, _, err = testutils.Get(fmt.Sprintf("%s%s", "https://localhost:32000", "/path")) c.Assert(err, NotNil) }
func (s *VESuite) TestFrontendUpdateBackend(c *C) { server1 := testutils.NewHandler(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("1")) }) defer server1.Close() server2 := testutils.NewHandler(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("2")) }) defer server2.Close() // Create two different backends b1, srv1, url1 := "bk1", "srv1", server1.URL _, err := s.client.Set(s.path("backends", b1, "backend"), `{"Type": "http"}`, 0) c.Assert(err, IsNil) _, err = s.client.Set(s.path("backends", b1, "servers", srv1), fmt.Sprintf(`{"URL": "%s"}`, url1), 0) c.Assert(err, IsNil) b2, srv2, url2 := "bk2", "srv2", server2.URL _, err = s.client.Set(s.path("backends", b2, "backend"), `{"Type": "http"}`, 0) c.Assert(err, IsNil) _, err = s.client.Set(s.path("backends", b2, "servers", srv2), fmt.Sprintf(`{"URL": "%s"}`, url2), 0) c.Assert(err, IsNil) // Add frontend inititally pointing to the first backend fId := "fr1" _, err = s.client.Set(s.path("frontends", fId, "frontend"), `{"Type": "http", "BackendId": "bk1", "Route": "Path(\"/path\")"}`, 0) c.Assert(err, IsNil) time.Sleep(time.Second) url := fmt.Sprintf("%s%s", s.serviceUrl, "/path") response, body, err := testutils.Get(url) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusOK) c.Assert(string(body), Equals, "1") // Update the backend _, err = s.client.Set(s.path("frontends", fId, "frontend"), `{"Type": "http", "BackendId": "bk2", "Route": "Path(\"/path\")"}`, 0) c.Assert(err, IsNil) time.Sleep(time.Second) response, body, err = testutils.Get(url) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusOK) c.Assert(string(body), Equals, "2") }
func (s *VESuite) TestExpiringServer(c *C) { server := testutils.NewResponder("e1") defer server.Close() server2 := testutils.NewResponder("e2") defer server2.Close() // Create backend and servers b, url, url2 := "bk1", server.URL, server2.URL srv, srv2 := "s1", "s2" _, err := s.client.Set(s.path("backends", b, "backend"), `{"Type": "http"}`, 0) c.Assert(err, IsNil) // This one will stay _, err = s.client.Set(s.path("backends", b, "servers", srv), fmt.Sprintf(`{"URL": "%s"}`, url), 0) c.Assert(err, IsNil) // This one will expire _, err = s.client.Set(s.path("backends", b, "servers", srv2), fmt.Sprintf(`{"URL": "%s"}`, url2), 2) c.Assert(err, IsNil) // Add frontend fId := "fr1" _, err = s.client.Set(s.path("frontends", fId, "frontend"), `{"Type": "http", "BackendId": "bk1", "Route": "Path(\"/path\")"}`, 0) c.Assert(err, IsNil) time.Sleep(time.Second) responses1 := make(map[string]bool) for i := 0; i < 3; i += 1 { response, body, err := testutils.Get(fmt.Sprintf("%s%s", s.serviceUrl, "/path")) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusOK) responses1[string(body)] = true } c.Assert(responses1, DeepEquals, map[string]bool{"e1": true, "e2": true}) // Now the second endpoint should expire time.Sleep(time.Second * 2) responses2 := make(map[string]bool) for i := 0; i < 3; i += 1 { response, body, err := testutils.Get(fmt.Sprintf("%s%s", s.serviceUrl, "/path")) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusOK) responses2[string(body)] = true } c.Assert(responses2, DeepEquals, map[string]bool{"e1": true}) }
func (s *CBSuite) TestRedirect(c *C) { handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello")) }) cb, err := New(handler, triggerNetRatio, Clock(s.clock), Fallback(fallbackRedirect)) c.Assert(err, IsNil) srv := httptest.NewServer(cb) defer srv.Close() cb.metrics = statsNetErrors(0.6) re, _, err := testutils.Get(srv.URL) c.Assert(err, IsNil) client := &http.Client{ CheckRedirect: func(req *http.Request, via []*http.Request) error { return fmt.Errorf("no redirects") }, } re, err = client.Get(srv.URL) c.Assert(err, NotNil) c.Assert(re.StatusCode, Equals, http.StatusFound) c.Assert(re.Header.Get("Location"), Equals, "http://localhost:5000") }
func (s *TraceSuite) TestTraceCaptureHeaders(c *C) { respHeaders := http.Header{ "X-Re-1": []string{"6", "7"}, "X-Re-2": []string{"2", "3"}, } handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { utils.CopyHeaders(w.Header(), respHeaders) w.Write([]byte("hello")) }) buf := &bytes.Buffer{} l := utils.NewFileLogger(buf, utils.INFO) trace := &bytes.Buffer{} t, err := New(handler, trace, Logger(l), RequestHeaders("X-Req-B", "X-Req-A"), ResponseHeaders("X-Re-1", "X-Re-2")) c.Assert(err, IsNil) srv := httptest.NewServer(t) defer srv.Close() reqHeaders := http.Header{"X-Req-A": []string{"1", "2"}, "X-Req-B": []string{"3", "4"}} re, _, err := testutils.Get(srv.URL+"/hello", testutils.Headers(reqHeaders)) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) var r *Record c.Assert(json.Unmarshal(trace.Bytes(), &r), IsNil) c.Assert(r.Request.Headers, DeepEquals, reqHeaders) c.Assert(r.Response.Headers, DeepEquals, respHeaders) }
func (s *STSuite) TestFileStreamingResponse(c *C) { srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello, this response is too large to fit in memory")) }) defer srv.Close() // forwarder will proxy the request to whatever destination fwd, err := forward.New() c.Assert(err, IsNil) // this is our redirect to server rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { req.URL = testutils.ParseURI(srv.URL) fwd.ServeHTTP(w, req) }) // stream handler will forward requests to redirect st, err := New(rdr, Logger(utils.NewFileLogger(os.Stdout, utils.INFO)), MemResponseBodyBytes(4)) c.Assert(err, IsNil) proxy := httptest.NewServer(st) defer proxy.Close() re, body, err := testutils.Get(proxy.URL) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) c.Assert(string(body), Equals, "hello, this response is too large to fit in memory") }
func (s *STSuite) TestCustomErrorHandler(c *C) { srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello, this response is too large")) }) defer srv.Close() // forwarder will proxy the request to whatever destination fwd, err := forward.New() c.Assert(err, IsNil) // this is our redirect to server rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { req.URL = testutils.ParseURI(srv.URL) fwd.ServeHTTP(w, req) }) // stream handler will forward requests to redirect errHandler := utils.ErrorHandlerFunc(func(w http.ResponseWriter, req *http.Request, err error) { w.WriteHeader(http.StatusTeapot) w.Write([]byte(http.StatusText(http.StatusTeapot))) }) st, err := New(rdr, Logger(utils.NewFileLogger(os.Stdout, utils.INFO)), MaxResponseBodyBytes(4), ErrorHandler(errHandler)) c.Assert(err, IsNil) proxy := httptest.NewServer(st) defer proxy.Close() re, _, err := testutils.Get(proxy.URL) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusTeapot) }
func (s *STSuite) TestNoBody(c *C) { srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) }) defer srv.Close() // forwarder will proxy the request to whatever destination fwd, err := forward.New() c.Assert(err, IsNil) // this is our redirect to server rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { req.URL = testutils.ParseURI(srv.URL) fwd.ServeHTTP(w, req) }) // stream handler will forward requests to redirect st, err := New(rdr, Logger(utils.NewFileLogger(os.Stdout, utils.INFO))) c.Assert(err, IsNil) proxy := httptest.NewServer(st) defer proxy.Close() re, _, err := testutils.Get(proxy.URL) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) }
// We've hit the limit and were able to proceed once the request has completed func (s *ConnLimiterSuite) TestCustomHandlers(c *C) { handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello")) }) errHandler := utils.ErrorHandlerFunc(func(w http.ResponseWriter, req *http.Request, err error) { w.WriteHeader(http.StatusTeapot) w.Write([]byte(http.StatusText(http.StatusTeapot))) }) buf := &bytes.Buffer{} log := utils.NewFileLogger(buf, utils.INFO) l, err := New(handler, headerLimit, 0, ErrorHandler(errHandler), Logger(log)) c.Assert(err, Equals, nil) srv := httptest.NewServer(l) defer srv.Close() re, _, err := testutils.Get(srv.URL, testutils.Header("Limit", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusTeapot) c.Assert(len(buf.String()), Not(Equals), 0) }
// Make sure that stream handler preserves TLS settings func (s *STSuite) TestPreservesTLS(c *C) { srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusOK) w.Write([]byte("ok")) }) defer srv.Close() // forwarder will proxy the request to whatever destination fwd, err := forward.New() c.Assert(err, IsNil) var t *tls.ConnectionState // this is our redirect to server rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { t = req.TLS req.URL = testutils.ParseURI(srv.URL) fwd.ServeHTTP(w, req) }) // stream handler will forward requests to redirect st, err := New(rdr, Logger(utils.NewFileLogger(os.Stdout, utils.INFO))) c.Assert(err, IsNil) proxy := httptest.NewUnstartedServer(st) proxy.StartTLS() defer proxy.Close() re, _, err := testutils.Get(proxy.URL) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) c.Assert(t, NotNil) }
func (s *STSuite) TestRequestLimitReached(c *C) { srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello")) }) defer srv.Close() // forwarder will proxy the request to whatever destination fwd, err := forward.New() c.Assert(err, IsNil) // this is our redirect to server rdr := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { req.URL = testutils.ParseURI(srv.URL) fwd.ServeHTTP(w, req) }) // stream handler will forward requests to redirect st, err := New(rdr, Logger(utils.NewFileLogger(os.Stdout, utils.INFO)), MaxRequestBodyBytes(4)) c.Assert(err, IsNil) proxy := httptest.NewServer(st) defer proxy.Close() re, _, err := testutils.Get(proxy.URL, testutils.Body("this request is too long")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusRequestEntityTooLarge) }
func (s *ServerSuite) TestMiddlewareCRUD(c *C) { e := testutils.NewResponder("Hi, I'm endpoint 1") defer e.Close() c.Assert(s.mux.Start(), IsNil) b := MakeBatch(Batch{ Addr: "localhost:31000", Route: `Path("/")`, URL: e.URL, }) c.Assert(s.mux.UpsertServer(b.BK, b.S), IsNil) c.Assert(s.mux.UpsertFrontend(b.F), IsNil) c.Assert(s.mux.UpsertListener(b.L), IsNil) // 1 request per second rl := MakeRateLimit(UID("rl"), 1, "client.ip", 1, 1) _, err := rl.Middleware.NewHandler(nil) c.Assert(err, IsNil) c.Assert(s.mux.UpsertMiddleware(b.FK, rl), IsNil) c.Assert(GETResponse(c, b.FrontendURL("/")), Equals, "Hi, I'm endpoint 1") re, _, err := testutils.Get(MakeURL(b.L, "/")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, 429) // too many requests c.Assert(s.mux.DeleteMiddleware(engine.MiddlewareKey{FrontendKey: b.FK, Id: rl.Id}), IsNil) for i := 0; i < 3; i++ { c.Assert(GETResponse(c, b.FrontendURL("/")), Equals, "Hi, I'm endpoint 1") c.Assert(GETResponse(c, b.FrontendURL("/")), Equals, "Hi, I'm endpoint 1") } }
func (s *RBSuite) TestRebalancerLive(c *C) { a, b := testutils.NewResponder("a"), testutils.NewResponder("b") defer a.Close() defer b.Close() fwd, err := forward.New() c.Assert(err, IsNil) lb, err := New(fwd) c.Assert(err, IsNil) rb, err := NewRebalancer(lb, RebalancerBackoff(time.Millisecond), RebalancerClock(s.clock)) c.Assert(err, IsNil) rb.UpsertServer(testutils.ParseURI(a.URL)) rb.UpsertServer(testutils.ParseURI(b.URL)) rb.UpsertServer(testutils.ParseURI("http://localhost:62345")) proxy := httptest.NewServer(rb) defer proxy.Close() for i := 0; i < 1000; i += 1 { testutils.Get(proxy.URL) if i%10 == 0 { s.clock.CurrentTime = s.clock.CurrentTime.Add(rb.backoffDuration + time.Second) } } // load balancer changed weights c.Assert(rb.servers[0].curWeight, Equals, FSMMaxWeight) c.Assert(rb.servers[1].curWeight, Equals, FSMMaxWeight) c.Assert(rb.servers[2].curWeight, Equals, 1) }
// Set up a frontend hit this frontend with request and make sure everything worked fine func (s *VESuite) TestFrontendCRUD(c *C) { called := false server := testutils.NewHandler(func(w http.ResponseWriter, r *http.Request) { called = true w.Write([]byte("Hi, I'm fine, thanks!")) }) defer server.Close() // Create a server b, srv, url := "bk1", "srv1", server.URL _, err := s.client.Set(s.path("backends", b, "backend"), `{"Type": "http"}`, 0) c.Assert(err, IsNil) _, err = s.client.Set(s.path("backends", b, "servers", srv), fmt.Sprintf(`{"URL": "%s"}`, url), 0) c.Assert(err, IsNil) // Add frontend fId := "fr1" _, err = s.client.Set(s.path("frontends", fId, "frontend"), `{"Type": "http", "BackendId": "bk1", "Route": "Path(\"/path\")"}`, 0) c.Assert(err, IsNil) time.Sleep(time.Second) response, _, err := testutils.Get(fmt.Sprintf("%s%s", s.serviceUrl, "/path")) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusOK) c.Assert(called, Equals, true) }
func (s *ServerSuite) TestBackendUpdateOptions(c *C) { e := testutils.NewHandler(func(w http.ResponseWriter, r *http.Request) { time.Sleep(10 * time.Millisecond) w.Write([]byte("slow server")) }) defer e.Close() c.Assert(s.mux.Start(), IsNil) b := MakeBatch(Batch{Addr: "localhost:11300", Route: `Path("/")`, URL: e.URL}) settings := b.B.HTTPSettings() settings.Timeouts = engine.HTTPBackendTimeouts{Read: "1ms"} b.B.Settings = settings c.Assert(s.mux.UpsertBackend(b.B), IsNil) c.Assert(s.mux.UpsertServer(b.BK, b.S), IsNil) c.Assert(s.mux.UpsertFrontend(b.F), IsNil) c.Assert(s.mux.UpsertListener(b.L), IsNil) re, _, err := testutils.Get(MakeURL(b.L, "/")) c.Assert(err, IsNil) c.Assert(re, NotNil) c.Assert(re.StatusCode, Equals, http.StatusGatewayTimeout) settings.Timeouts = engine.HTTPBackendTimeouts{Read: "20ms"} b.B.Settings = settings c.Assert(s.mux.UpsertBackend(b.B), IsNil) c.Assert(GETResponse(c, b.FrontendURL("/")), Equals, "slow server") }
func (s *ServerSuite) TestFrontendUpdateRoute(c *C) { c.Assert(s.mux.Start(), IsNil) e := testutils.NewResponder("hola") defer e.Close() b := MakeBatch(Batch{ Addr: "localhost:31000", Route: `Path("/")`, URL: e.URL, }) c.Assert(s.mux.UpsertServer(b.BK, b.S), IsNil) c.Assert(s.mux.UpsertFrontend(b.F), IsNil) c.Assert(s.mux.UpsertListener(b.L), IsNil) c.Assert(GETResponse(c, b.FrontendURL("/")), Equals, "hola") b.F.Route = `Path("/new")` c.Assert(s.mux.UpsertFrontend(b.F), IsNil) c.Assert(GETResponse(c, b.FrontendURL("/new")), Equals, "hola") response, _, err := testutils.Get(MakeURL(b.L, "/")) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusNotFound) }
func (s *RewriteSuite) TestSameHeaderMulti(c *C) { var outURL string handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { outURL = rawURL(req) w.Write([]byte("hello")) }) rh, err := newRewriteHandler(handler, &Rewrite{ "^http://localhost/(foo)/(bar)$", `http://localhost/$1/{{.Request.Header.Get "X-Header"}}/$2/{{.Request.Header.Get "X-Header"}}`, false, false}) c.Assert(rh, NotNil) c.Assert(err, IsNil) srv := httptest.NewServer(rh) defer srv.Close() re, _, err := testutils.Get(srv.URL+"/foo/bar", testutils.Host("localhost"), testutils.Header("X-Header", "baz")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) c.Assert(outURL, Equals, "http://localhost/foo/baz/bar/baz") }
func (s *VESuite) TestHTTPListenerCRUD(c *C) { called := false server := testutils.NewHandler(func(w http.ResponseWriter, r *http.Request) { called = true w.Write([]byte("Hi, I'm fine, thanks!")) }) defer server.Close() b, srv, url := "bk1", "srv1", server.URL _, err := s.client.Set(s.path("backends", b, "backend"), `{"Type": "http"}`, 0) c.Assert(err, IsNil) _, err = s.client.Set(s.path("backends", b, "servers", srv), fmt.Sprintf(`{"URL": "%s"}`, url), 0) c.Assert(err, IsNil) // Add frontend fId := "fr1" _, err = s.client.Set(s.path("frontends", fId, "frontend"), `{"Type": "http", "BackendId": "bk1", "Route": "Path(\"/path\")"}`, 0) c.Assert(err, IsNil) time.Sleep(time.Second) response, _, err := testutils.Get(fmt.Sprintf("%s%s", s.serviceUrl, "/path")) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusOK) // Add HTTP listener l1 := "l1" listener, err := engine.NewListener(l1, "http", "tcp", "localhost:31000", "", nil) c.Assert(err, IsNil) bytes, err := json.Marshal(listener) c.Assert(err, IsNil) s.client.Set(s.path("listeners", l1), string(bytes), 0) time.Sleep(time.Second) _, _, err = testutils.Get(fmt.Sprintf("%s%s", "http://localhost:31000", "/path")) c.Assert(err, IsNil) c.Assert(called, Equals, true) _, err = s.client.Delete(s.path("listeners", l1), true) c.Assert(err, IsNil) time.Sleep(time.Second) _, _, err = testutils.Get(fmt.Sprintf("%s%s", "http://localhost:31000", "/path")) c.Assert(err, NotNil) }
// Removing the server resets the state func (s *RBSuite) TestRebalancerReset(c *C) { a, b, d := testutils.NewResponder("a"), testutils.NewResponder("b"), testutils.NewResponder("d") defer a.Close() defer b.Close() defer d.Close() fwd, err := forward.New() c.Assert(err, IsNil) lb, err := New(fwd) c.Assert(err, IsNil) newMeter := func() (Meter, error) { return &testMeter{}, nil } rb, err := NewRebalancer(lb, RebalancerMeter(newMeter), RebalancerClock(s.clock), RebalancerLogger(s.log)) c.Assert(err, IsNil) rb.UpsertServer(testutils.ParseURI(a.URL)) rb.UpsertServer(testutils.ParseURI(b.URL)) rb.UpsertServer(testutils.ParseURI(d.URL)) rb.servers[0].meter.(*testMeter).rating = 0.3 rb.servers[1].meter.(*testMeter).rating = 0 rb.servers[2].meter.(*testMeter).rating = 0 proxy := httptest.NewServer(rb) defer proxy.Close() for i := 0; i < 6; i += 1 { testutils.Get(proxy.URL) testutils.Get(proxy.URL) s.clock.CurrentTime = s.clock.CurrentTime.Add(rb.backoffDuration + time.Second) } // load balancer changed weights c.Assert(rb.servers[0].curWeight, Equals, 1) c.Assert(rb.servers[1].curWeight, Equals, FSMMaxWeight) c.Assert(rb.servers[2].curWeight, Equals, FSMMaxWeight) // Removing servers has reset the state rb.RemoveServer(testutils.ParseURI(d.URL)) c.Assert(rb.servers[0].curWeight, Equals, 1) c.Assert(rb.servers[1].curWeight, Equals, 1) }
func seq(c *C, url string, repeat int) []string { out := []string{} for i := 0; i < repeat; i++ { _, body, err := testutils.Get(url) c.Assert(err, IsNil) out = append(out, string(body)) } return out }
// If the rate set from the HTTP header has more then one rate for the same // time period defined, then the one mentioned in the list last is used. func (s *RateLimitSuite) TestRequestProcessingAmbiguousConfig(c *C) { // Given rl, _ := FromOther( RateLimit{ PeriodSeconds: 1, Requests: 1, Burst: 1, Variable: "client.ip", RateVar: "request.header.X-Rates", clock: s.clock, }) handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("hello")) }) rli, err := rl.NewHandler(handler) c.Assert(err, IsNil) srv := httptest.NewServer(rli) defer srv.Close() // When/Then: The last of configured rates with the same period is applied, // which 2 request/second, note that the default rate is 1 request/second. hdr := testutils.Header("X-Rates", `[{"PeriodSeconds": 1, "Requests": 10}, {"PeriodSeconds": 1, "Requests": 2}]`) re, _, err := testutils.Get(srv.URL, hdr) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) re, _, err = testutils.Get(srv.URL, hdr) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) re, _, err = testutils.Get(srv.URL, hdr) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, 429) s.clock.Sleep(time.Second) re, _, err = testutils.Get(srv.URL, hdr) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) }
// We've hit the limit and were able to proceed once the request has completed func (s *ConnLimiterSuite) TestHitLimitAndRelease(c *C) { wait := make(chan bool) proceed := make(chan bool) handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if req.Header.Get("wait") != "" { proceed <- true <-wait } w.Write([]byte("hello")) }) l, err := New(handler, headerLimit, 1) c.Assert(err, Equals, nil) srv := httptest.NewServer(l) defer srv.Close() go func() { re, _, err := testutils.Get(srv.URL, testutils.Header("Limit", "a"), testutils.Header("wait", "yes")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) }() <-proceed re, _, err := testutils.Get(srv.URL, testutils.Header("Limit", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, 429) // request from another source succeeds re, _, err = testutils.Get(srv.URL, testutils.Header("Limit", "b")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) // Once the first request finished, next one succeeds close(wait) re, _, err = testutils.Get(srv.URL, testutils.Header("Limit", "a")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) }
func (s *VESuite) TestBackendUpdateSettings(c *C) { server := testutils.NewHandler(func(w http.ResponseWriter, r *http.Request) { time.Sleep(50 * time.Millisecond) w.Write([]byte("tc: update upstream options")) }) defer server.Close() b, srv, url := "bk1", "srv1", server.URL _, err := s.client.Set(s.path("backends", b, "backend"), `{"Type": "http", "Settings": {"Timeouts": {"Read":"10ms"}}}`, 0) c.Assert(err, IsNil) _, err = s.client.Set(s.path("backends", b, "servers", srv), fmt.Sprintf(`{"URL": "%s"}`, url), 0) c.Assert(err, IsNil) // Add frontend fId := "fr1" _, err = s.client.Set(s.path("frontends", fId, "frontend"), `{"Type": "http", "BackendId": "bk1", "Route": "Path(\"/path\")"}`, 0) c.Assert(err, IsNil) // Wait for the changes to take effect time.Sleep(time.Second) // Make sure request times out response, _, err := testutils.Get(fmt.Sprintf("%s%s", s.serviceUrl, "/path")) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusGatewayTimeout) // Update backend timeout _, err = s.client.Set(s.path("backends", b, "backend"), `{"Type": "http", "Settings": {"Timeouts": {"Read":"100ms"}}}`, 0) c.Assert(err, IsNil) // Wait for the changes to take effect time.Sleep(time.Second) response, body, err := testutils.Get(fmt.Sprintf("%s%s", s.serviceUrl, "/path")) c.Assert(err, IsNil) c.Assert(response.StatusCode, Equals, http.StatusOK) c.Assert(string(body), Equals, "tc: update upstream options") }