Exemple #1
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)
}
Exemple #2
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)
}
Exemple #3
0
func (s *RewriteSuite) TestMultipleHeaders(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 "Y-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"), testutils.Header("Y-Header", "bam"))

	c.Assert(err, IsNil)
	c.Assert(re.StatusCode, Equals, http.StatusOK)
	c.Assert(outURL, Equals, "http://localhost/foo/baz/bar/bam")
}
Exemple #4
0
// 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)
}
Exemple #5
0
// 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 TestDefaultWhenSpecifiedLanguageNotInConfig(t *testing.T) {
	t.Log("Set default language when the specified language is not in config")

	language := "en_GB"
	server := setupTestServer("test_multiple.yml", "https://127.0.0.1", setupTestHandler(acceptLanguageHeader, language, t))
	defer server.Close()
	testutils.Get(server.URL+"?_l=es_SP", testutils.Header("Origin", "https://127.0.0.1"))
}
func TestSpecifiedWithMultipleCurrencies(t *testing.T) {
	t.Log("Set specified when there are multiple Currencies")

	currency := "franc"
	server := setupTestServer("test_multiple.yml", "https://127.0.0.1", setupTestHandler(acceptCurrencyHeader, currency, t))
	defer server.Close()

	testutils.Get(server.URL+"?_c=franc", testutils.Header("Origin", "https://127.0.0.1"))
}
func TestSpecifiedWithMultipleLanguages(t *testing.T) {
	t.Log("Set specified language when there are multiple languages")

	language := "fr_FR"
	server := setupTestServer("test_multiple.yml", "https://127.0.0.1", setupTestHandler(acceptLanguageHeader, language, t))
	defer server.Close()
	testutils.Get(server.URL+"?_l=fr_FR", testutils.Header("Origin", "https://127.0.0.1"))

}
func TestDefaultWithMultipleCurrencies(t *testing.T) {
	t.Log("Set default when there are multiple Currencies")

	currency := "eur"
	server := setupTestServer("test_multiple.yml", "https://127.0.0.1", setupTestHandler(acceptCurrencyHeader, currency, t))
	defer server.Close()

	testutils.Get(server.URL, testutils.Header("Origin", "https://127.0.0.1"))
}
func TestDefaultWithMultipleLanguages(t *testing.T) {
	t.Log("Set default when there are multiple languages")

	language := "en_GB"
	server := setupTestServer("test_multiple.yml", "https://127.0.0.1", setupTestHandler(acceptLanguageHeader, language, t))
	defer server.Close()

	testutils.Get(server.URL, testutils.Header("Origin", "https://127.0.0.1"))
}
func TestDefaultWhenSpecifiedCurrencyNotInConfig(t *testing.T) {
	t.Log("Set defaul when specified currency is not in config")

	currency := "eur"
	server := setupTestServer("test_multiple.yml", "https://127.0.0.1", setupTestHandler(acceptCurrencyHeader, currency, t))
	defer server.Close()

	testutils.Get(server.URL+"?_c=yen", testutils.Header("Origin", "https://127.0.0.1"))
}
Exemple #12
0
// 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 TestLanguageHeader(t *testing.T) {
	t.Log("Set language header when provided")
	locale := "en_US"
	server := setupTestServer("test1.yml", "https://127.0.0.1", setupTestHandler(acceptLanguageHeader, locale, t))
	defer server.Close()

	_, _, err := testutils.Get(server.URL, testutils.Header("Origin", "https://127.0.0.1"))

	if err != nil {
		t.Errorf("Error while processing request: %+v", err)
	}
}
func TestCurrencyHeader(t *testing.T) {
	t.Log("Set currency header when provided")
	currency := "usd"
	server := setupTestServer("test1.yml", "https://127.0.0.1", setupTestHandler(acceptCurrencyHeader, currency, t))
	defer server.Close()

	_, _, err := testutils.Get(server.URL, testutils.Header("Origin", "https://127.0.0.1"))

	if err != nil {
		t.Errorf("Error while processing request: %+v", err)
	}
}
Exemple #15
0
// We've failed to extract client ip
func (s *LimiterSuite) TestFailure(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, faultyExtract, 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.StatusInternalServerError)
}
Exemple #16
0
func (s *RewriteSuite) TestDontRewriteResponseBody(c *C) {
	handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.Write([]byte(`{"foo": "{{.Request.Header.Get "X-Header"}}"}`))
	})

	rh, err := newRewriteHandler(handler, &Rewrite{"", "", false, false})
	c.Assert(rh, NotNil)
	c.Assert(err, IsNil)

	srv := httptest.NewServer(rh)
	defer srv.Close()

	re, body, err := testutils.Get(srv.URL,
		testutils.Host("localhost"),
		testutils.Header("X-Header", "bar"))

	c.Assert(re.StatusCode, Equals, http.StatusOK)
	c.Assert(string(body), Equals, `{"foo": "{{.Request.Header.Get "X-Header"}}"}`)
}
Exemple #17
0
func (s *RewriteSuite) TestRewriteInQuery(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\\?(.*)=(.*)", `http://localhost/foo?$1={{.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?a=b", testutils.Host("localhost"), testutils.Header("X-Header", "xxx"))
	c.Assert(err, IsNil)
	c.Assert(re.StatusCode, Equals, http.StatusOK)
	c.Assert(outURL, Equals, "http://localhost/foo?a=xxx")
}
Exemple #18
0
// TestContentLength makes sure Content-Length is re-calculated if body rewrite is enabled.
func (s *RewriteSuite) TestContentLength(c *C) {
	handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.Header().Set("Content-Length", "45")
		w.WriteHeader(200)
		w.Write([]byte(`{"foo": "{{.Request.Header.Get "X-Header"}}"}`))
	})

	rh, err := newRewriteHandler(handler, &Rewrite{"", "", true, false})
	c.Assert(rh, NotNil)
	c.Assert(err, IsNil)

	srv := httptest.NewServer(rh)
	defer srv.Close()

	re, _, _ := testutils.Get(srv.URL,
		testutils.Host("localhost"),
		testutils.Header("X-Header", "bar"))

	c.Assert(re.Header.Get("Content-Length"), Equals, "14")
}
Exemple #19
0
func (s *TraceSuite) TestHandler(c *C) {
	os.Remove("/tmp/vulcand_trace_test.sock")
	unixAddr, err := net.ResolveUnixAddr("unixgram", "/tmp/vulcand_trace_test.sock")
	c.Assert(err, IsNil)
	conn, err := net.ListenUnixgram("unixgram", unixAddr)
	c.Assert(err, IsNil)
	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"}})
}