Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

### Bug fixes:

- fix(ngwaf/v1/rules): Fix Typing on rate limit struct. [#729](https://github.com/fastly/go-fastly/pull/729)

### Dependencies:

## [v11.1.0](https://github.com/fastly/go-fastly/releases/tag/v11.1.0) (2025-08-04)
Expand Down
20 changes: 15 additions & 5 deletions fastly/ngwaf/v1/rules/api_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,25 @@ type CreateGroupCondition struct {
// CreateRateLimit defines how rate limit rules are enforced.
type CreateRateLimit struct {
// List of client identifiers used for rate limiting. Can only be length 1 or 2.
ClientIdentifiers []*string
ClientIdentifiers []*CreateClientIdentifier `json:"client_identifiers"`
// Duration in seconds for the rate limit.
Duration *int
Duration *int `json:"duration"`
// Time interval for the rate limit in seconds (60, 600, or 3600 minutes).
Interval *int
Interval *int `json:"interval"`
// The signal used to count requests.
Signal *string
Signal *string `json:"signal"`
// Rate limit threshold (between 1 and 10000).
Threshold *int
Threshold *int `json:"threshold"`
}

// CreateClientIdentifier is the client identifier for rate limit rules.
type CreateClientIdentifier struct {
// Key is the of the client identifier
Key *string `json:"key,omitempty"`
// Name is the name of the client identifier
Name *string `json:"name,omitempty"`
// Type is the type of the client identifier
Type *string `json:"type"`
}

// Create creates a new rule.
Expand Down
4 changes: 4 additions & 0 deletions fastly/ngwaf/v1/rules/api_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ type RateLimit struct {

// ClientIdentifiers defines how a client is identified.
type ClientIdentifier struct {
// Key is the of the client identifier
Key string `json:"key"`
// Name is the name of the client identifier
Name string `json:"name"`
// Type is the type of identifier.
Type string `json:"type"`
}
Expand Down
42 changes: 27 additions & 15 deletions fastly/ngwaf/v1/rules/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,8 @@ func runRateLimitRuleTest(t *testing.T, scopeType common.ScopeType, appliesToID
threshold := 1
interval := 60
duration := 300
clientIdentifier := "client1"
clientIdentifier := "ip"
clientIdentifierName := "name"

// Create a test rule.
var rule *Rule
Expand All @@ -638,11 +639,16 @@ func runRateLimitRuleTest(t *testing.T, scopeType common.ScopeType, appliesToID
GroupOperator: &groupOperator,
Enabled: &enabled,
RateLimit: &CreateRateLimit{
Signal: &signal.ReferenceID,
Threshold: &threshold,
Interval: &interval,
Duration: &duration,
ClientIdentifiers: []*string{&clientIdentifier},
Signal: &signal.ReferenceID,
Threshold: &threshold,
Interval: &interval,
Duration: &duration,
ClientIdentifiers: []*CreateClientIdentifier{
{
Type: &clientIdentifier,
Name: &clientIdentifierName,
},
},
},
Actions: []*CreateAction{
{
Expand Down Expand Up @@ -761,7 +767,8 @@ func runRateLimitRuleTest(t *testing.T, scopeType common.ScopeType, appliesToID
assert.Equal(signal.ReferenceID, action.Signal)

assert.Equal(duration, rule.RateLimit.Duration)
assert.Equal("ip", rule.RateLimit.ClientIdentifiers[0].Type)
assert.Equal(clientIdentifier, rule.RateLimit.ClientIdentifiers[0].Type)
assert.Equal(clientIdentifierName, rule.RateLimit.ClientIdentifiers[0].Name)
assert.Equal(interval, rule.RateLimit.Interval)
assert.Equal(signal.ReferenceID, rule.RateLimit.Signal)
assert.Equal(threshold, rule.RateLimit.Threshold)
Expand Down Expand Up @@ -839,7 +846,8 @@ func runRateLimitRuleTest(t *testing.T, scopeType common.ScopeType, appliesToID
assert.Equal(signal.ReferenceID, testRuleAction.Signal)

assert.Equal(duration, rule.RateLimit.Duration)
assert.Equal("ip", rule.RateLimit.ClientIdentifiers[0].Type)
assert.Equal(clientIdentifier, rule.RateLimit.ClientIdentifiers[0].Type)
assert.Equal(clientIdentifierName, rule.RateLimit.ClientIdentifiers[0].Name)
assert.Equal(interval, rule.RateLimit.Interval)
assert.Equal(signal.ReferenceID, rule.RateLimit.Signal)
assert.Equal(threshold, rule.RateLimit.Threshold)
Expand Down Expand Up @@ -899,7 +907,6 @@ func runRateLimitRuleTest(t *testing.T, scopeType common.ScopeType, appliesToID
updatedThreshold := 2
updatedInterval := 600
updatedDuration := 600
updatedClientIdentifier := "updatedClient1"

// Updated Single Conditions
updatedOperator1 := "does_not_equal"
Expand Down Expand Up @@ -943,11 +950,16 @@ func runRateLimitRuleTest(t *testing.T, scopeType common.ScopeType, appliesToID
GroupOperator: &updatedGroupOperator,
Enabled: &updatedEnabled,
RateLimit: &UpdateRateLimit{
Signal: &signal.ReferenceID,
Threshold: &updatedThreshold,
Interval: &updatedInterval,
Duration: &updatedDuration,
ClientIdentifiers: []*string{&updatedClientIdentifier},
Signal: &signal.ReferenceID,
Threshold: &updatedThreshold,
Interval: &updatedInterval,
Duration: &updatedDuration,
ClientIdentifiers: []*UpdateClientIdentifier{
{
Name: &clientIdentifierName,
Type: &clientIdentifier,
},
},
},
Actions: []*UpdateAction{
{
Expand Down Expand Up @@ -1039,7 +1051,7 @@ func runRateLimitRuleTest(t *testing.T, scopeType common.ScopeType, appliesToID

// Validate Rate Limit
assert.Equal(updatedDuration, updatedRule.RateLimit.Duration)
assert.Equal("ip", updatedRule.RateLimit.ClientIdentifiers[0].Type)
assert.Equal(clientIdentifier, updatedRule.RateLimit.ClientIdentifiers[0].Type)
assert.Equal(updatedInterval, updatedRule.RateLimit.Interval)
assert.Equal(signal.ReferenceID, updatedRule.RateLimit.Signal)
assert.Equal(updatedThreshold, updatedRule.RateLimit.Threshold)
Expand Down
12 changes: 11 additions & 1 deletion fastly/ngwaf/v1/rules/api_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ type UpdateGroupCondition struct {
// UpdateRateLimit defines how rate limit rules are enforced.
type UpdateRateLimit struct {
// List of client identifiers used for rate limiting. Can only be length 1 or 2.
ClientIdentifiers []*string
ClientIdentifiers []*UpdateClientIdentifier
// Duration in seconds for the rate limit.
Duration *int
// Time interval for the rate limit in seconds (60, 600, or 3600 minutes).
Expand All @@ -112,6 +112,16 @@ type UpdateRateLimit struct {
Threshold *int
}

// UpdateClientIdentifier is the client identifier for rate limit rules.
type UpdateClientIdentifier struct {
// Key is the of the client identifier
Key *string `json:"key,omitempty"`
// Name is the name of the client identifier
Name *string `json:"name,omitempty"`
// Type is the type of the client identifier
Type *string `json:"type"`
}

// Update updates a rule.
func Update(ctx context.Context, c *fastly.Client, i *UpdateInput) (*Rule, error) {
if i.RuleID == nil {
Expand Down
10 changes: 5 additions & 5 deletions fastly/ngwaf/v1/rules/fixtures/account_create_rule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ interactions:
Content-Type:
- application/json
User-Agent:
- FastlyGo/11.0.0 (+github.com/fastly/go-fastly; go1.24.2)
- FastlyGo/11.1.0 (+github.com/fastly/go-fastly; go1.24.2)
url: https://api.fastly.com/ngwaf/v1/rules
method: POST
response:
body: |
{"id":"6890c9f63ff692d75c740181","type":"request","scope":{"type":"account","applies_to":["*"]},"enabled":true,"description":"test","group_operator":"all","request_logging":"sampled","conditions":[{"type":"single","field":"ip","operator":"equals","value":"127.0.0.1"},{"type":"single","field":"path","operator":"equals","value":"/login"},{"type":"single","field":"agent_name","operator":"equals","value":"host-001"},{"type":"group","group_operator":"all","conditions":[{"type":"single","field":"country","operator":"equals","value":"AD"},{"type":"single","field":"method","operator":"equals","value":"POST"}]},{"type":"group","group_operator":"any","conditions":[{"type":"single","field":"protocol_version","operator":"equals","value":"HTTP/1.0"},{"type":"single","field":"method","operator":"equals","value":"HEAD"},{"type":"single","field":"domain","operator":"equals","value":"example.com"}]}],"actions":[{"type":"block"}],"created_at":"2025-08-04T14:55:50Z","updated_at":"2025-08-04T14:55:50Z"}
{"id":"6891213903859c47e4acd3b0","type":"request","scope":{"type":"account","applies_to":["*"]},"enabled":true,"description":"test","group_operator":"all","request_logging":"sampled","conditions":[{"type":"single","field":"ip","operator":"equals","value":"127.0.0.1"},{"type":"single","field":"path","operator":"equals","value":"/login"},{"type":"single","field":"agent_name","operator":"equals","value":"host-001"},{"type":"group","group_operator":"all","conditions":[{"type":"single","field":"country","operator":"equals","value":"AD"},{"type":"single","field":"method","operator":"equals","value":"POST"}]},{"type":"group","group_operator":"any","conditions":[{"type":"single","field":"protocol_version","operator":"equals","value":"HTTP/1.0"},{"type":"single","field":"method","operator":"equals","value":"HEAD"},{"type":"single","field":"domain","operator":"equals","value":"example.com"}]}],"actions":[{"type":"block"}],"created_at":"2025-08-04T21:08:09Z","updated_at":"2025-08-04T21:08:09Z"}
headers:
Accept-Ranges:
- bytes
Expand All @@ -26,7 +26,7 @@ interactions:
Content-Type:
- application/json
Date:
- Mon, 04 Aug 2025 14:55:54 GMT
- Mon, 04 Aug 2025 21:08:12 GMT
Pragma:
- no-cache
Server:
Expand All @@ -42,9 +42,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-chi-klot8100176-CHI, cache-ewr-kewr1740055-EWR
- cache-chi-klot8100099-CHI, cache-nyc-kteb1890053-NYC
X-Timer:
- S1754319351.522795,VS0,VE3689
- S1754341690.873543,VS0,VE2426
status: 201 Created
code: 201
duration: ""
10 changes: 5 additions & 5 deletions fastly/ngwaf/v1/rules/fixtures/account_delete_rule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ interactions:
form: {}
headers:
User-Agent:
- FastlyGo/11.0.0 (+github.com/fastly/go-fastly; go1.24.2)
url: https://api.fastly.com/ngwaf/v1/rules/6890c9f63ff692d75c740181
- FastlyGo/11.1.0 (+github.com/fastly/go-fastly; go1.24.2)
url: https://api.fastly.com/ngwaf/v1/rules/6891213903859c47e4acd3b0
method: DELETE
response:
body: ""
Expand All @@ -19,7 +19,7 @@ interactions:
Content-Type:
- application/json
Date:
- Mon, 04 Aug 2025 14:56:01 GMT
- Mon, 04 Aug 2025 21:08:18 GMT
Pragma:
- no-cache
Server:
Expand All @@ -35,9 +35,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-chi-kigq8000027-CHI, cache-ewr-kewr1740055-EWR
- cache-chi-kigq8000080-CHI, cache-nyc-kteb1890053-NYC
X-Timer:
- S1754319358.012203,VS0,VE3642
- S1754341695.316645,VS0,VE2685
status: 204 No Content
code: 204
duration: ""
12 changes: 6 additions & 6 deletions fastly/ngwaf/v1/rules/fixtures/account_get_rule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ interactions:
form: {}
headers:
User-Agent:
- FastlyGo/11.0.0 (+github.com/fastly/go-fastly; go1.24.2)
url: https://api.fastly.com/ngwaf/v1/rules/6890c9f63ff692d75c740181
- FastlyGo/11.1.0 (+github.com/fastly/go-fastly; go1.24.2)
url: https://api.fastly.com/ngwaf/v1/rules/6891213903859c47e4acd3b0
method: GET
response:
body: |
{"id":"6890c9f63ff692d75c740181","type":"request","scope":{"type":"account","applies_to":["*"]},"enabled":true,"description":"test","group_operator":"all","request_logging":"sampled","conditions":[{"type":"single","field":"ip","operator":"equals","value":"127.0.0.1"},{"type":"single","field":"path","operator":"equals","value":"/login"},{"type":"single","field":"agent_name","operator":"equals","value":"host-001"},{"type":"group","group_operator":"all","conditions":[{"type":"single","field":"country","operator":"equals","value":"AD"},{"type":"single","field":"method","operator":"equals","value":"POST"}]},{"type":"group","group_operator":"any","conditions":[{"type":"single","field":"protocol_version","operator":"equals","value":"HTTP/1.0"},{"type":"single","field":"method","operator":"equals","value":"HEAD"},{"type":"single","field":"domain","operator":"equals","value":"example.com"}]}],"actions":[{"type":"block"}],"created_at":"2025-08-04T14:55:50Z","updated_at":"2025-08-04T14:55:50Z"}
{"id":"6891213903859c47e4acd3b0","type":"request","scope":{"type":"account","applies_to":["*"]},"enabled":true,"description":"test","group_operator":"all","request_logging":"sampled","conditions":[{"type":"single","field":"ip","operator":"equals","value":"127.0.0.1"},{"type":"single","field":"path","operator":"equals","value":"/login"},{"type":"single","field":"agent_name","operator":"equals","value":"host-001"},{"type":"group","group_operator":"all","conditions":[{"type":"single","field":"country","operator":"equals","value":"AD"},{"type":"single","field":"method","operator":"equals","value":"POST"}]},{"type":"group","group_operator":"any","conditions":[{"type":"single","field":"protocol_version","operator":"equals","value":"HTTP/1.0"},{"type":"single","field":"method","operator":"equals","value":"HEAD"},{"type":"single","field":"domain","operator":"equals","value":"example.com"}]}],"actions":[{"type":"block"}],"created_at":"2025-08-04T21:08:09Z","updated_at":"2025-08-04T21:08:09Z"}
headers:
Accept-Ranges:
- bytes
Expand All @@ -22,7 +22,7 @@ interactions:
Content-Type:
- application/json
Date:
- Mon, 04 Aug 2025 14:55:54 GMT
- Mon, 04 Aug 2025 21:08:12 GMT
Pragma:
- no-cache
Server:
Expand All @@ -38,9 +38,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-chi-kigq8000027-CHI, cache-ewr-kewr1740055-EWR
- cache-chi-kigq8000080-CHI, cache-nyc-kteb1890053-NYC
X-Timer:
- S1754319354.237176,VS0,VE100
- S1754341692.330457,VS0,VE108
status: 200 OK
code: 200
duration: ""
8 changes: 4 additions & 4 deletions fastly/ngwaf/v1/rules/fixtures/account_list_rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interactions:
form: {}
headers:
User-Agent:
- FastlyGo/11.0.0 (+github.com/fastly/go-fastly; go1.24.2)
- FastlyGo/11.1.0 (+github.com/fastly/go-fastly; go1.24.2)
url: https://api.fastly.com/ngwaf/v1/rules
method: GET
response:
Expand All @@ -22,7 +22,7 @@ interactions:
Content-Type:
- application/json
Date:
- Mon, 04 Aug 2025 14:55:50 GMT
- Mon, 04 Aug 2025 21:08:09 GMT
Pragma:
- no-cache
Server:
Expand All @@ -38,9 +38,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-chi-klot8100176-CHI, cache-ewr-kewr1740055-EWR
- cache-chi-klot8100099-CHI, cache-nyc-kteb1890053-NYC
X-Timer:
- S1754319350.393942,VS0,VE109
- S1754341690.751129,VS0,VE109
status: 200 OK
code: 200
duration: ""
12 changes: 6 additions & 6 deletions fastly/ngwaf/v1/rules/fixtures/account_update_rule.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ interactions:
Content-Type:
- application/json
User-Agent:
- FastlyGo/11.0.0 (+github.com/fastly/go-fastly; go1.24.2)
url: https://api.fastly.com/ngwaf/v1/rules/6890c9f63ff692d75c740181
- FastlyGo/11.1.0 (+github.com/fastly/go-fastly; go1.24.2)
url: https://api.fastly.com/ngwaf/v1/rules/6891213903859c47e4acd3b0
method: PATCH
response:
body: |
{"id":"6890c9f63ff692d75c740181","type":"request","scope":{"type":"account","applies_to":["*"]},"enabled":false,"description":"updated test","group_operator":"any","request_logging":"none","conditions":[{"type":"single","field":"ip","operator":"does_not_equal","value":"10.0.0.1"},{"type":"single","field":"path","operator":"does_not_equal","value":"/admin"},{"type":"single","field":"agent_name","operator":"matches","value":"bot-*"},{"type":"group","group_operator":"any","conditions":[{"type":"single","field":"country","operator":"does_not_equal","value":"US"},{"type":"single","field":"method","operator":"does_not_equal","value":"PUT"}]},{"type":"group","group_operator":"all","conditions":[{"type":"single","field":"protocol_version","operator":"does_not_equal","value":"HTTP/2.0"},{"type":"single","field":"method","operator":"does_not_equal","value":"OPTIONS"},{"type":"single","field":"domain","operator":"does_not_equal","value":"internal.example"}]}],"actions":[{"type":"allow"}],"created_at":"2025-08-04T14:55:50Z","updated_at":"2025-08-04T14:55:50Z"}
{"id":"6891213903859c47e4acd3b0","type":"request","scope":{"type":"account","applies_to":["*"]},"enabled":false,"description":"updated test","group_operator":"any","request_logging":"none","conditions":[{"type":"single","field":"ip","operator":"does_not_equal","value":"10.0.0.1"},{"type":"single","field":"path","operator":"does_not_equal","value":"/admin"},{"type":"single","field":"agent_name","operator":"matches","value":"bot-*"},{"type":"group","group_operator":"any","conditions":[{"type":"single","field":"country","operator":"does_not_equal","value":"US"},{"type":"single","field":"method","operator":"does_not_equal","value":"PUT"}]},{"type":"group","group_operator":"all","conditions":[{"type":"single","field":"protocol_version","operator":"does_not_equal","value":"HTTP/2.0"},{"type":"single","field":"method","operator":"does_not_equal","value":"OPTIONS"},{"type":"single","field":"domain","operator":"does_not_equal","value":"internal.example"}]}],"actions":[{"type":"allow"}],"created_at":"2025-08-04T21:08:09Z","updated_at":"2025-08-04T21:08:09Z"}
headers:
Accept-Ranges:
- bytes
Expand All @@ -27,7 +27,7 @@ interactions:
Content-Type:
- application/json
Date:
- Mon, 04 Aug 2025 14:55:57 GMT
- Mon, 04 Aug 2025 21:08:15 GMT
Pragma:
- no-cache
Server:
Expand All @@ -43,9 +43,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-chi-kigq8000027-CHI, cache-ewr-kewr1740055-EWR
- cache-chi-kigq8000080-CHI, cache-nyc-kteb1890053-NYC
X-Timer:
- S1754319354.356905,VS0,VE3634
- S1754341692.469019,VS0,VE2820
status: 200 OK
code: 200
duration: ""
Loading