You've already forked pocketbase
mirror of
https://github.com/pocketbase/pocketbase.git
synced 2025-11-28 08:47:55 +02:00
added the triggered rate limit rule in the error log details
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
## v0.29.0 (WIP)
|
||||||
|
|
||||||
|
- Added the triggered rate rimit rule in the error log `details`.
|
||||||
|
|
||||||
|
|
||||||
## v0.28.4
|
## v0.28.4
|
||||||
|
|
||||||
- Added global JSVM `toBytes()` helper to return the bytes slice representation of a value such as io.Reader or string (_other types are first serialized to Go string_).
|
- Added global JSVM `toBytes()` helper to return the bytes slice representation of a value such as io.Reader or string (_other types are first serialized to Go string_).
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package apis
|
package apis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -167,7 +168,7 @@ func checkRateLimit(e *core.RequestEvent, rtId string, rule core.RateLimitRule)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !rt.isAllowed(key) {
|
if !rt.isAllowed(key) {
|
||||||
return e.TooManyRequestsError("", nil)
|
return e.TooManyRequestsError("", errors.New("triggered rate limit rule: "+rule.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -704,3 +704,13 @@ func (c RateLimitRule) Validate() error {
|
|||||||
func (c RateLimitRule) DurationTime() time.Duration {
|
func (c RateLimitRule) DurationTime() time.Duration {
|
||||||
return time.Duration(c.Duration) * time.Second
|
return time.Duration(c.Duration) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the rule.
|
||||||
|
func (c RateLimitRule) String() string {
|
||||||
|
raw, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return c.Label // extremely rare case
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(raw)
|
||||||
|
}
|
||||||
|
|||||||
@@ -687,7 +687,7 @@ func TestRateLimitsFindRateLimitRule(t *testing.T) {
|
|||||||
func TestRateLimitRuleValidate(t *testing.T) {
|
func TestRateLimitRuleValidate(t *testing.T) {
|
||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
name string
|
name string
|
||||||
config core.RateLimitRule
|
rule core.RateLimitRule
|
||||||
expectedErrors []string
|
expectedErrors []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
@@ -784,7 +784,7 @@ func TestRateLimitRuleValidate(t *testing.T) {
|
|||||||
|
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.name, func(t *testing.T) {
|
t.Run(s.name, func(t *testing.T) {
|
||||||
result := s.config.Validate()
|
result := s.rule.Validate()
|
||||||
|
|
||||||
tests.TestValidationErrors(t, result, s.expectedErrors)
|
tests.TestValidationErrors(t, result, s.expectedErrors)
|
||||||
})
|
})
|
||||||
@@ -793,7 +793,7 @@ func TestRateLimitRuleValidate(t *testing.T) {
|
|||||||
|
|
||||||
func TestRateLimitRuleDurationTime(t *testing.T) {
|
func TestRateLimitRuleDurationTime(t *testing.T) {
|
||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
config core.RateLimitRule
|
rule core.RateLimitRule
|
||||||
expected time.Duration
|
expected time.Duration
|
||||||
}{
|
}{
|
||||||
{core.RateLimitRule{}, 0 * time.Second},
|
{core.RateLimitRule{}, 0 * time.Second},
|
||||||
@@ -801,8 +801,8 @@ func TestRateLimitRuleDurationTime(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, s := range scenarios {
|
for i, s := range scenarios {
|
||||||
t.Run(fmt.Sprintf("%d_%d", i, s.config.Duration), func(t *testing.T) {
|
t.Run(fmt.Sprintf("%d_%d", i, s.rule.Duration), func(t *testing.T) {
|
||||||
result := s.config.DurationTime()
|
result := s.rule.DurationTime()
|
||||||
|
|
||||||
if result != s.expected {
|
if result != s.expected {
|
||||||
t.Fatalf("Expected duration %d, got %d", s.expected, result)
|
t.Fatalf("Expected duration %d, got %d", s.expected, result)
|
||||||
@@ -810,3 +810,37 @@ func TestRateLimitRuleDurationTime(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRateLimitRuleString(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
name string
|
||||||
|
rule core.RateLimitRule
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"empty",
|
||||||
|
core.RateLimitRule{},
|
||||||
|
`{"label":"","audience":"","duration":0,"maxRequests":0}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"all fields",
|
||||||
|
core.RateLimitRule{
|
||||||
|
Label: "POST /a/b/",
|
||||||
|
Duration: 1,
|
||||||
|
MaxRequests: 2,
|
||||||
|
Audience: core.RateLimitRuleAudienceAuth,
|
||||||
|
},
|
||||||
|
`{"label":"POST /a/b/","audience":"@auth","duration":1,"maxRequests":2}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range scenarios {
|
||||||
|
t.Run(s.name, func(t *testing.T) {
|
||||||
|
result := s.rule.String()
|
||||||
|
|
||||||
|
if result != s.expected {
|
||||||
|
t.Fatalf("Expected string\n%s\ngot\n%s", s.expected, result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user