func (s *AuthSuite) TestRequestBadPassword(c *C) { a := &AuthMiddleware{authKeys: []authKey{{username: "******", password: "******"}}} h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "treasure") }) auth, err := a.NewHandler(h) c.Assert(err, IsNil) srv := httptest.NewServer(auth) defer srv.Close() // bad pass re, _, err := testutils.Get(srv.URL, testutils.BasicAuth(a.authKeys[0].username, "open please")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusUnauthorized) // missing header re, _, err = testutils.Get(srv.URL) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusUnauthorized) // malformed header re, _, err = testutils.Get(srv.URL, testutils.Header("Authorization", "blablabla=")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusUnauthorized) }
// We've hit the limit and were able to proceed on the next time run func (s *LimiterSuite) TestHitLimit(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) // Second later, the request from this ip will succeed 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) }
// 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) }
// 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) 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") }
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) }
// 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) 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 *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 *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 *FwdSuite) TestForwardedProto(c *C) { var proto string srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) { proto = req.Header.Get(XForwardedProto) w.Write([]byte("hello")) }) defer srv.Close() buf := &bytes.Buffer{} l := utils.NewFileLogger(buf, utils.INFO) f, err := New(Logger(l)) c.Assert(err, IsNil) proxy := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { req.URL = testutils.ParseURI(srv.URL) f.ServeHTTP(w, req) }) tproxy := httptest.NewUnstartedServer(proxy) tproxy.StartTLS() defer tproxy.Close() re, _, err := testutils.Get(tproxy.URL) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) c.Assert(proto, Equals, "https") c.Assert(strings.Contains(buf.String(), "tls"), Equals, true) }
// Makes sure hop-by-hop headers are removed func (s *FwdSuite) TestForwardedHeaders(c *C) { var outHeaders http.Header srv := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) { outHeaders = req.Header w.Write([]byte("hello")) }) defer srv.Close() f, err := New(Rewriter(&HeaderRewriter{TrustForwardHeader: true, Hostname: "hello"})) c.Assert(err, IsNil) proxy := testutils.NewHandler(func(w http.ResponseWriter, req *http.Request) { req.URL = testutils.ParseURI(srv.URL) f.ServeHTTP(w, req) }) defer proxy.Close() headers := http.Header{ XForwardedProto: []string{"httpx"}, XForwardedFor: []string{"192.168.1.1"}, XForwardedServer: []string{"foobar"}, XForwardedHost: []string{"upstream-foobar"}, } re, _, err := testutils.Get(proxy.URL, testutils.Headers(headers)) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) c.Assert(outHeaders.Get(XForwardedProto), Equals, "httpx") c.Assert(strings.Contains(outHeaders.Get(XForwardedFor), "192.168.1.1"), Equals, true) c.Assert(strings.Contains(outHeaders.Get(XForwardedHost), "upstream-foobar"), Equals, true) c.Assert(outHeaders.Get(XForwardedServer), Equals, "hello") }
// 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 *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 *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 *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) }
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) 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 *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) }
// 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) }
// 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) }
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 *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 *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 *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 *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 (s *TraceSuite) TestHandler(c *C) { conn := setUnixSocket(c) defer conn.Close() outC := make(chan []byte, 1000) closeC := make(chan bool) defer close(closeC) go func() { for { buf := make([]byte, 65536) bytes, err := conn.Read(buf) if err != nil { return } outbuf := make([]byte, bytes) copy(outbuf, buf) select { case <-closeC: return case outC <- outbuf: continue } } }() responder := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { w.Header().Add("X-Resp-A", "h2") w.Write([]byte("hello")) }) h, err := New("syslog:///tmp/vulcand_trace_test.sock", []string{"X-Req-A"}, []string{"X-Resp-A"}) c.Assert(err, IsNil) handler, err := h.NewHandler(responder) c.Assert(err, IsNil) srv := httptest.NewServer(handler) defer srv.Close() re, _, err := testutils.Get(srv.URL+"/hello", testutils.Header("X-Req-A", "yo")) c.Assert(err, IsNil) c.Assert(re.StatusCode, Equals, http.StatusOK) var buf []byte select { case buf = <-outC: case <-time.After(10 * time.Millisecond): c.Fatalf("timeout") } vals := strings.Split(string(buf), SyslogPrefix) var r *oxytrace.Record c.Assert(json.Unmarshal([]byte(vals[1]), &r), IsNil) c.Assert(r.Request.URL, Equals, "/hello") c.Assert(r.Request.Headers, DeepEquals, http.Header{"X-Req-A": []string{"yo"}}) c.Assert(r.Response.Headers, DeepEquals, http.Header{"X-Resp-A": []string{"h2"}}) }