// 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") } }
// 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()) } }
// 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) } }