Example #1
0
// ensures that Limit.Match exhibits expected behavior
func TestLimitMatch(t *testing.T) {
	data, err := ioutil.ReadFile("../example.yaml")
	if err != nil {
		t.Fatal(err)
	}
	config, err := config.LoadAndValidateYaml(data)
	if err != nil {
		t.Fatal(err)
	}

	// matches name: Authorization, match: bearer (from example.yaml)
	matchers, err := resolveMatchers(config.Limits["basic-simple"].Matches)
	// excludes path: /special/resoures/.*
	excludes, err := resolveMatchers(config.Limits["basic-simple"].Excludes)

	limit := limit{
		name: "test-limit",
		matcher: requestMatcher{
			Matches:  matchers,
			Excludes: excludes,
		},
	}

	request := common.Request{
		"path": "/resources/123",
		"headers": http.Header{
			"Authorization": []string{"Basic 12345"},
		},
	}
	if !limit.Match(request) {
		t.Error("Expected basic-easy to match request")
	}

	request = common.Request{
		"path": "/special/resources/123",
		"headers": http.Header{
			"Authorization": []string{"Basic 12345"},
		},
	}
	if limit.Match(request) {
		t.Error("Request with Excludes path should NOT match basic-easy")
	}

	request = common.Request{
		"path":    "/special/resources/123",
		"headers": http.Header{},
	}
	if limit.Match(request) {
		t.Error("Request without Auth header should NOT match basic-easy")
	}
}
Example #2
0
// test that matcher errors are bubbled up
func TestBadConfiguration(t *testing.T) {

	configBuf := bytes.NewBufferString(`
proxy:
  handler: http
  host: http://proxy.example.com
  listen: :8080
storage:
  type: memory
limits:
  test:
    interval: 15  # in seconds
    max: 200
`)

	// header matchers are verified
	configBuf.WriteString(`
    keys:
      headers:
        - Authorization
    matches:
      headers:
        match_any:
          - "Authorization": "Bearer.*"
          - name: "X-Forwarded-For"
`)
	config, err := config.LoadAndValidateYaml(configBuf.Bytes())
	if err != nil {
		t.Fatal(err)
	}

	if _, err := New("test", config.Limits["test"], Storage{}); err == nil {
		t.Fatal("expected error")
	} else if !strings.Contains(err.Error(), "InvalidMatcherConfig: headers") {
		t.Errorf("Expected a InvalidMatcherConfig error, got different error: %s", err.Error())
	}

}
Example #3
0
// Make sure limit.Add adds requests to different buckets
func TestLimitAdd(t *testing.T) {
	data, err := ioutil.ReadFile("../example.yaml")
	if err != nil {
		t.Fatal(err)
	}
	conf, err := config.LoadAndValidateYaml(data)
	if err != nil {
		t.Fatal(err)
	}

	limitconfig := config.Limit{
		Interval: 100,
		Max:      3,
		// matches name: Authorization, match: bearer (from example.yaml)
		Matches: conf.Limits["basic-simple"].Matches,
		// excludes path: /special/resoures/.*
		Excludes: conf.Limits["basic-simple"].Excludes,
		Keys:     conf.Limits["basic-simple"].Keys,
	}

	lim, err := New("test-limit", limitconfig, memory.New())
	limit := lim.(*limit)
	if err != nil {
		t.Error("Could not initialize test-limit")
	}

	request := common.Request{
		"path": "/special/resources/123",
		"headers": http.Header{
			"Authorization": []string{"Basic 12345"},
		},
	}
	for i := uint(1); i < 4; i++ {
		bucketStatus, err := limit.Add(request)
		if err != nil {
			t.Errorf("Error while adding to limit test-limit: %s", err.Error())
		}
		if bucketStatus.Remaining != limit.max-i {
			t.Errorf("Expected remaining %d, found: %d",
				limit.max-i, bucketStatus.Remaining)
		}
	}

	bucketStatus, err := limit.Add(request)
	if err == nil {
		t.Fatal("expected error")
	}
	if err != leakybucket.ErrorFull {
		t.Errorf("Expected leakybucket.ErrorFull error, got: %s", err.Error())
	}

	request2 := common.Request{
		"path": "/special/resources/123",
		"headers": http.Header{
			"Authorization": []string{"Basic ABC"},
		},
	}
	bucketStatus, err = limit.Add(request2)
	if err != nil {
		t.Errorf("Error while adding to limit test-limit: %s", err.Error())
	}
	if bucketStatus.Remaining != 2 {
		t.Errorf("Expected remaining %d, found: %d",
			2, bucketStatus.Remaining)
	}
}